作者:刘武东 来自: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 794From http://www.blogjava.net/Al ... -
ECLIPSE ANT OutOfMemoryError
2011-08-04 17:23 970ANT 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 1795weblogic:weblogic8.1 数据库:MySql ... -
log4j 邮件
2011-01-24 15:54 0<!-- 设置上下文参数 --> ... -
tomcat weblogic
2010-12-01 11:25 1820EJB 层基本搞定,以前测试 EJB 也都是写一个 appli ... -
ant weblogic “local class incompatible: stream classdesc serialVersionUI”
2010-11-29 12:41 2146weblogic.management.Management ... -
Debugging with the Maven Jetty Plugin in Eclipse
2010-11-15 17:42 999debug: http://docs.codehaus.or ... -
maven tomcat eclipse debug
2010-11-15 17:36 1919from: http://bandaidprogrammin ... -
maven app tomcat 部署
2010-11-11 15:56 1263修改pom.xml,添加如下配置: <build ... -
Maven Cargo Tomcat 部署
2010-11-11 15:49 1735pom.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 2298方式一: 四舍五入 double f = ... -
java中实现xml schema 验证文件
2009-11-16 20:05 3837XML 是可扩展标记语言,也就是说其中的标记我们可以按照我们 ...
相关推荐
从Java类库看设计模式
从Java类库看设计模式.pdf
包含以下文件: Java设计模式-图解-附代码.pdf 从Java类库看设计模式.doc 六大UML类图关系.docx 认识UML类图元素_java之UML.doc 设计模式6大原则.doc 设计模式学习笔记.doc 深入浅出设计模式(中文版).pdf
java,设计模式中的一种,状态设计模式。
设计模式贯穿于整个Java体系,我们所用的大小型框架和Java本身类库里面都用了大量的设计模式。初学者有些地方不懂没关系,知道有这回事就行了,背下每一种设计模式结构的角色(UML类图),随着你平时本身学习Java的...
交互式用户界面模型的特点,提出了一种基于java/swing和两种设计模式的交互 式界面的设计思想与具体实现方案。该方案包含用户界面代理,能提供给用户图 形的可视化方式来设计界面的视图,和控制器的设计;这套方案...
java 类库 源码
本书内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化 Java编程的各种宝贵经验,深入阐述Java虚拟机执行Java程序的原理。...
容器中的设计模式, 容器源码分析 - List, 容器源码分析 - Map, 容器源码分析 - 并发容 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,意味着可以在不同的操作系统上...
Java是一种高级的面向对象的程序设计语言,它具有广泛的应用和强大的跨平台特性。Java语言于1995年由Sun公司推出,由Java之父詹姆斯高斯林设计。Java的设计目标是提供一种易学易用、功能强大的编程语言,使开发人员...
用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字 Java波浪文字,一个利用...
设计模式 java 迭代器模式
用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字 Java波浪文字,一个利用...
《Java 面向对象编程》内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化Java编程的各种宝贵经验,深入阐述Java虚拟机执行...
用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字 Java波浪文字,一个利用...
JAVA短信网关平台(值得一看).rar Java绘制图片火焰效果.rar Java编写的HTML浏览器.rar Java编写的山寨QQ,多人聊天+用户在线.rar Java编写的显示器显示模式检测程序.rar Java编写的网页版魔方游戏.rar java聊天室 ...
本书内容由浅入深,紧密结合实际,利用大量典型实例,详细讲解Java面向对象的编程思想、编程语法和设计模式,介绍常见Java类库的用法,总结优化Java编程的各种宝贵经验,深入阐述Java虚拟机执行Java程序的原理。...