作者:刘武东 来自:IBM
在这一部分的内容中,介绍的是一个相对简单但功能强大的模式:Observer模式。希望通过这部分地叙述,大家看了之后,能够对设计模式
有一个比较全面地,感性的认识。
很多时候,对于一个设计来说(软件上的,建筑上的,或者它他工业上的),经验是至关重要的。好的经验给我们以指导,并节约我们的时间;坏的经验则给我们
以借鉴,可以减少失败的风险。然而,从知识层面上来讲,经验只是作为一种工作的积累而存在于个人的大脑中的,很难被传授或者记录。为了解决这样的问题,人
们提出了所谓的模式的概念。所谓模式,是指在一个特定背景下,反复出现的问题解决方案。模式是经验的文档化。 软件模式的概念现在比较的
广泛,涉及到分析,设计,体系结构,编码,测试,重构等软件构造生命期中的各个部分。这儿主要讨论的是设计模式,指的是在软件设计过程中反复出现的一些问
题的解决方法了。不过我们一般在提到设计模式的时候,一般都是指GOF的经典书《Design Pattern--Elements of
Reusable Object-Oriented Software》出现的23个模式,因而,它是具体的针对于面向对象软件设计过程的。
从全局上看来,模式代表了一种语言,一种被文档化的经验,甚至是一种文化。往往很多不方便描叙,或者描叙起来很复杂的问题,用模式语言来叙说,会让听者
产生心领神会的感觉。当然,这需要交流双方都能够很好地把握模式语言的含义。然而,这并不是一件容易的事情。模式在各个人的理解上往往存在差异,这篇文章
旨在从一个具体的应用角度:Java类库,来阐叙设计模式。并结合具体的例子,希望能够加深大家对设计模式的理解。 这儿说的Java类
库,其实并没有局限于JDK本身,还包括了一些其他的类库中的例子,比如JAXP等(当然,下一个版本的JDK中也会包含JAXP了)。其实设计模式的思
想现在应用的如此广泛,无论在什么样的设计中,只要稍微大一点的设计,都可以找到很多很多设计模式的踪迹,或者说都不可避免的用到设计模式。下面所讲的设
计模式,大部分都是GOF的那部经典中出现过的23个模式,然而,还有一些,比如MVC,并不属于那里。一般的来讲,我们认为GOF的23个模式是一些中
级的模式,在它下面还可以抽象出一些更为一般的低层的模式,在其上也可以通过组合来得到一些高级的模式。当然,这儿的低中高的区别,如同区别不同的语言一
样,并没有优劣之分,仅仅是在应用层面上的区别。 Observer模式
Observer模式的功用,是希望两个(或多个)对象,我们称之为Subject和Observer,当一方的状态发生改变的时候,另一方能够得到通
知。也就是说,作为Observer的一方,能够监视到Subject的某个特定的状态变化,并为之做出反应。一个简单的例子就是:当一个用户视图中的数
据被用户改变后,后端的数据库能够得到更新,而当数据库被其他方式更新后,用户视图中的数据显示也会随之改变。
在JDK中实际上有一个对Observer模式的简单的实现:就是类java.util.Observerable和接口
java.util.Observer。java.util.Observerable类对应于Subject,而java.util.Observer
就是观察者了。JDK中并没有把这两个部分都设计为接口,而是让类java.util.Observerable提供了部分的实现,简化了许多编程的工
作。当然,这也减少了一定的灵活性。 下面列出了Observer和Observeral的函数列表,及其简单的功能说明 java.util.Observer:
public void update(Observable obs, Object obj) java.util.Observable:
public void addObserver(Observer obs) public void deleteObserver(Observer obs) public void deleteObservers() public int countObservers() protected void setChanged() protected void clearChanged()
public boolean hasChanged() public void notifyObservers(Object obj) public void notifyObservers()
因而在Java中应用Observer就很简单了,需要做的是:让需要被观察的Subject对象继承java.util.Observerable,
让需要观察的对象实现java.util.Observer接口,然后用java.util.Observerable的
addObserver(Observer
obj)方法把Observer注册到Subject对象中。这已经完成了大部分的工作了。然后调用java.util.Observerable的
notifyObservers(Object
arg)等方法,就可以实现Observer模式的机理。我们来看一个简单使用了这个模式的例子。这个例子有三个
类:FrameSubject,DateSubject,FrameObject和EntryClass,FrameSubject中用户可以设置被观察
的值,然后自动的会在FrameObject中显示出来,DateSubject封装被观察的值,并且充当Observer模式中的Subject。 public class FrameSubject extends JFrame {
我认为在JDK中这个Observer模式的实现,对于一般的Observer模式的应用,已经是非常的足够了的。但是一方面它用一个类来实现了
Subject,另一方面它使用Vector来保存Subject对于Observer的引用,这虽然简化了编程的过程,但会限制它在一些需要更为灵活,
复杂的设计中的应用,有时候(虽然这种情况不多),我们还不得不重新编写新的Subject对象和额外的Manager对象来实现更为复杂的
Observer模式的应用。 小结:
这一部分主要的讨论了模式的概念。随着现代
软件工业的不断进步,软件系统的规模的日益扩大,越来越需要对某些个不断出现的问题进行模式化思维,以成功的经验或者失败的教训来减少软件开发失败的风
险。模式代表了一种文档化的经验,它为某一类的问题提供了最好(或者说很好)的解决方案,使得即使不是经验丰富的软件工程师,也能够根据模式来构建相对成
功的系统。本节给出的一个Obverser模式的示例,比较好的说明了这一点。Obverser模式主要解决在对象间的状态映射或者镜像的问题。
图一:Obverser模式的类图
java.util.Observer
接口很简单,只定义了这一个方法,狭义的按照Observer模式的说法,Observer应该在这个方法中调用Subject的getXXX()方法来
取得最新的状态,而实际上,你可以只是在其中对Subject的某些事件进行响应。这便是Java中的代理事件模型的一个雏形--对事件进行响应。只不
过,在Observer模式中将事件特定化为某个状态/数据的改变了。
向Subject注册一个Observer。也就是把这个Observer对象添加到了一个java.util.Observable内部的列表中。在
JDK中对于这个列表是简单的通过一个java.util.Vector类来实现的,而实际上,在一些复杂的Observer模式的应用中,需要把这个部
分单另出来形成一个Manager类,来管理Subject和Observer之间的映射。这样,Subject和Observer进一步的被解藕,程序
也会具有更大的灵活性。
从Subject中删除一个已注册了Observer的引用。
从Subjec中删除所有注册的Observer的引用。
返回注册在Subject中的Observer个数。
设置一个内部的标志以指明这个Ovserver的状态已经发生改变。注意这是一个protected方法,也就是说只能在Observer类和其子类中被调用,而在其它的类中是看不到这个方法的。
清除上叙的内部标志。它在notifyObservers()方法内部被自动的调用,以指明Subject的状态的改变已经传递到Ovserver中了。
确定Subject的状态是否发生了改变。
它首先检查那个内部的标志,以判断状态是否改变,如果是的话,它会调用注册在Subject中的每个Observer的update()方法。在JDK
中这个方法内部是作为synchronized来实现的,也就是如果发生多个线程同时争用一个java.util.Observerable的
notifyObservers()方法的话,他们必须按调度的等待着顺序执行。在某些特殊的情况下,这会有一些潜在的问题:可能在等待的过程中,一个刚
刚被加入的Observer会被遗漏没有被通知到,而一个刚刚被删除了的Observer会仍然收到它已经不想要了的通知。
等价于调用了notifyObservers(null)。
…………
//因为无法使用多重继承,这儿就只能使用对象组合的方式来引入一个
//java.util.Observerable对象了。
DateSubject subject=new DateSubject();
//这个方法转发添加Observer消息到DateSubject。
public void registerObserver(java.util.Observer o){
subject.addObserver(o);
}
//数据改变,事件被触发后调用notifyObservers()来通知Observer。
void jButton1_actionPerformed(ActionEvent e) {
subject.setWidthInfo(Integer.parseInt(jTextField1.getText()));
subject.setHeightInfo(Integer.parseInt(jTextField2.getText()));
subject.notifyObservers();
}
……………
}
public class DateSubject extends Observable {
//封装被观察的数据
private int widthInfo;
private int heightInfo;
public int getWidthInfo() {
return widthInfo;
}
public void setWidthInfo(int widthInfo) {
this.widthInfo = widthInfo;
//数据改变后,setChanged()必须被调用,否则notifyObservers()方法会不起作用
this.setChanged();
}
public void setHeightInfo(int heightInfo) {
this.heightInfo = heightInfo;
this.setChanged();
}
public int getHeightInfo() {
return heightInfo;
}
}
public class FrameObserver extends JFrame implements java.util.Observer {
…………
//观察的数据
int widthInfo=0;
int heightInfo=0;
//在update()方法中实现对数据的更新和其它必要的反应。
public void update(Observable o, Object arg) {
DateSubject subject=(DateSubject) o;
widthInfo=subject.getWidthInfo();
heightInfo=subject.getHeightInfo();
jLabel1.setText("The heightInfo from subject is: ");
jLabel3.setText(String.valueOf(heightInfo));
jLabel2.setText("The widthInfo from subject is: ");
jLabel4.setText(String.valueOf(widthInfo));
}
……………
}
public class EntryClass {
public static void main(String[] args) {
……………
FrameSubject frame = new FrameSubject();
FrameObserver frame2=new FrameObserver();
//在Subject中注册Observer,将两者联系在一起
frame.registerObserver(frame2);
…………
frame.setVisible(true);
frame2.setVisible(true);
……………
}
}
参考资源:
- Software Patterns: James O. Coplien, Bell Laboratories,The Hillside Group
- 设计模式:可复用面向对象软件的基础 机械工业出版社
- Java2类库增补版 机械工业出版社
- 可视化面向对象建模技术 北京航天航空工业大学出版社
- JDK1.3源代码
- UML用户指南 机械工业出版社
发表评论
-
深入分析 Java 中的中文编码问题
2011-11-16 07:45 0几种常见的编码格式 ... -
Java 编码
2011-11-16 07:44 0http://zhidao.baidu.com/quest ... -
java字符编码原理解析
2011-11-16 07:43 0可以理解为计算机没 ... -
HttpClient
2011-11-03 11:07 824From http://www.blogjava.net/Al ... -
ECLIPSE ANT OutOfMemoryError
2011-08-04 17:23 1011ANT BUILD MEMORY ERROR: [cl ... -
JDBC BATCH
2011-07-05 14:58 0PreparedStatement ps = conn.pre ... -
OUT OF MEMORY WHEN BUILD
2011-02-22 17:47 01, ANT BUILD: In Eclipse op ... -
spring weblogic jndi
2011-02-16 09:18 1837weblogic:weblogic8.1 数据库:MySql ... -
log4j 邮件
2011-01-24 15:54 0<!-- 设置上下文参数 --> ... -
tomcat weblogic
2010-12-01 11:25 1862EJB 层基本搞定,以前测试 EJB 也都是写一个 appli ... -
ant weblogic “local class incompatible: stream classdesc serialVersionUI”
2010-11-29 12:41 2227weblogic.management.Management ... -
Debugging with the Maven Jetty Plugin in Eclipse
2010-11-15 17:42 1035debug: http://docs.codehaus.or ... -
maven tomcat eclipse debug
2010-11-15 17:36 1946from: http://bandaidprogrammin ... -
maven app tomcat 部署
2010-11-11 15:56 1307修改pom.xml,添加如下配置: <build ... -
Maven Cargo Tomcat 部署
2010-11-11 15:49 1769pom.xml中<build>下添加如下代码: ... -
java中读取配置文件各种方法
2010-09-07 12:31 01。使用Java.util.Properties类的load( ... -
ThreadGroup
2010-05-25 08:47 0在Java中每个线程都属于某个线程组(ThreadGroup) ... -
java Excel 导出
2010-03-28 20:06 0public void createExcel(OutputS ... -
java小数保留两位小数
2009-11-19 16:49 2337方式一: 四舍五入 double f = ... -
java中实现xml schema 验证文件
2009-11-16 20:05 3877XML 是可扩展标记语言,也就是说其中的标记我们可以按照我们 ...
相关推荐
### 从Java类库看设计模式之Observer模式详解 #### 一、引言 在软件开发过程中,常常遇到需要在不同对象之间建立依赖关系的情况,其中一个对象的状态变化会影响到另一个对象的行为。这种需求可以用设计模式中的...
本文以Java类库为视角,深入探讨了设计模式的核心概念、分类以及在Java中的具体应用案例,特别是组合模式和观察者模式。 设计模式的概念起源于对软件开发过程中遇到的各种问题的总结和归纳。它是一套经验证的、可...
除了Observer模式,Java类库还体现了其他多种设计模式。如Singleton模式,用于确保一个类只有一个实例,并提供全局访问点,如`java.lang.Runtime`类;Factory模式,用于创建对象的接口,如`java.sql.DriverManager`...
Java 类库为开发者提供了丰富的工具集,涵盖了从基础的数据类型处理到高级的网络通信等多个方面。本文档旨在介绍 Java 中一些常用的类库,帮助初学者更好地理解和使用这些类库。尽管文档内容并不全面,但包含了...
Struts 是一个基于MVC设计模式的Web应用框架,用于处理HTTP请求和响应: - Struts Action 用来处理来自用户的请求,执行业务逻辑,并将结果返回给用户。 - Struts Taglib 提供了一系列JSP标签,方便在页面上创建用户...
同时,这也是一个很好的学习 Java 设计模式和最佳实践的方式,因为许多类库的设计都遵循了 SOLID 原则和面向对象设计的原则。因此,"java2 类库" 对于 Java 学习者来说是一本经典的参考材料,它不仅提供了丰富的代码...
Java类库大全是一个集合了众多Java开发中常用和实用类库的资源集合,旨在为开发者提供便利,提高开发效率。这个资源包包含了丰富的Java库,覆盖了从基础数据类型操作到复杂的网络通信、多线程处理、数据库操作、图形...
《Java类库手册》是一本全面介绍Java编程语言类库的参考资料,对于深入理解和使用Java技术至关重要。在Java开发中,类库是开发者最常打交道的部分,它包含了各种预定义的类和接口,提供了丰富的功能,帮助我们实现...
每个包通常包含了一组具有相似功能的类和接口,这些包构成了Java类库的基础框架。 ##### 常见包简介 - **java.applet**:提供了创建Applet所需的所有类。 - **java.awt.\***:提供了用于创建用户界面以及绘制和...
其中,**Decorator模式**作为一种常用的结构型设计模式,在Java类库中有着广泛的应用。本文将详细介绍Decorator模式的概念、应用场景及其在Java I/O系统中的具体实现。 #### 二、Decorator模式简介 **Decorator...
12. **设计模式**:如单例、工厂、观察者等,例子将展示如何在Java中实现常见的设计模式,提升代码的复用性和可维护性。 通过研究这些例子,开发者不仅可以巩固Java基础知识,还能学习到如何在实际项目中灵活运用...
### Java设计模式详解 ...通过以上内容可以看出,《Java设计模式PDF》这本书不仅提供了对各种设计模式的详细介绍,而且还结合了大量的示例代码和实用建议,对于Java开发者来说是一本非常有价值的参考书。
本资源包含了一个常用的Java类库的源代码,这对于Java程序员来说是一份宝贵的学习和参考材料。 首先,Java类库中最基础的部分是Java标准库(Java Standard Library),它包括了Java语言的核心API,如集合框架(java...
总的来说,这个Java类库为开发者提供了一种简化的方式来处理数据库操作,通过面向对象的接口,结合Java反射技术,实现了类似Ruby on Rails的ActiveRecord模式。这使得开发者可以避免编写大量的SQL代码,而是专注于...
例如,它可能包含了一些数据结构、算法或者设计模式的实现,帮助读者更好地理解和应用Java编程思想。 在Java编程中,类库的使用可以极大地提高开发效率。例如,标准库如Java.util和Java.io提供了大量用于处理集合、...
Java软件架构设计模式是软件开发过程中一套经过实践验证的、可复用的设计解决方案,它针对在构建大型复杂系统时常见的问题和挑战提供了指导原则。这些模式源于经验,可以帮助开发者更高效地组织代码,提高系统的可...
Java设计模式是面向对象编程中的一种重要概念,它们为解决常见的软件设计问题提供了模板。这份“JAVA设计模式”帮助文档将深入探讨这些模式及其在Java中的应用。 1. **单例模式(Singleton)** 单例模式确保一个类...