<%@ page contentType="text/html; charset=gb2312"%> JDK Observer设计模式之研究
网站公告:   ◆北天JAVA技术网热情为java爱好者服务,本网内容包括JAVA(JSP、servlet、EJB、webservice、j2ee、javabean、应用服务器、JavaScript),数据库(MYSQL、SQL Server、Sybase、Oracle、DB2、数据库综合知识),设计研究(设计模式、Struts、Spring、Hibernate、设计框架、设计综合知识),WEB2.0新技术(主要介绍AJAX),以及各种技术的入门、实例、例子等等,欢迎各位多来坐坐!◆  诚邀各位JAVA爱好者加盟!◆  本网站内容丰富,更新快,保证每周20篇以上!  
加入收藏
设为首页
联系站长
承接项目
  相关资源:网站首页 | 免费培训学院 | 技术论坛 | JAVA聊天室 | 作家专栏 | 开发工具 | 认证考试 | 会员俱乐部
  JAVA技术初学者园地 | jsp与servlet | javascript | Java源代码 | EJB | web service | 应用服务器 | JAVA综合知识
  设计研究设计模式 | 设计框架 | Struts | Spring | Hibernate | 开源项目 | 面向对象设计 | 设计综合知识
  数 据 库MYSQL | SQL Server | Sybase | Oracle | DB2 | Informix | Access | 数据库综合知识
  其他资源:AJAX新技术 | 网站开发 | ERP软件 | OA办公软件 | 商业智能BI | 开发综合知识 | 承接项目 | 项目试用

 
 
JDK Observer设计模式之研究
     发布者: 发布时间:2007-09-23
目前设计模式的介绍性文章越来越多,但设计模式的研究性文章仍然比较欠缺,这着实让人觉得有点遗憾。本文旨在抛砖引玉,具体分析一下java中jdk自带的observer设计模式(下文如没特别指出,observer设计模式就意指java中jdk自带的observer设计模式)的实现。
1. Observer 设计模式概要
Observer设计模式在GOF里属于行为设计模式。JDK里提供的observer设计模式的实现由java.util.Observable类和java.util.Observer接口组成。从名字上可以清楚的看出两者在Observer 设计模式中分别扮演的角色:Observer是观察者角色,Observable是被观察目标(subject)角色。
Observable是一个封装subject基本功能的类,比如注册observer(attach功能),注销observer(detatch功能)等。这些功能是任何一个扮演observerable角色的类都需要实现的,从这一点上来讲,JDK里将这些通用功能专门封装在一个类里,显得合情合理。通常情况下,我们的类只要从Observerable类派生就可以称为observerable角色类,使用非常简单。
2. 使用observer设计模式存在的困难
但我们不得不注意到,在项目实际开发当中,情况往往要复杂得多。java不支持多继承特性在很多时候是阻碍我们使用observer设计模式的绊脚石。比如说,我们设计的一个类已经是某个类的派生类,在这种情况下同时想让它扮演observerable角色将变得麻烦。如何实现“多继承”的效果是摆在我们面前的一大难题。下面我们首先分析一下Observable类。
3. Observable类“触发通知”的原理
Observable必须“有变化”才能触发通知observer这一任务,这是它的本质体现。查看源码便可知一二。Observerable部分源码如下:
//……省略……
private boolean changed = false;
//……省略……
public void notifyObservers(Object arg) {
//……省略……
Object[] arrLocal;
synchronized (this) {
//……省略……
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}

//……省略……

protected synchronized void setChanged() {
changed = true;
}

protected synchronized void clearChanged() {
changed = false;
}
正如粗的斜体标注部分所示,在notifyObservers(Object arg) 方法里if (!changed)
return;语句告诉我们,若changed属性值为false,将直接返回,根本不会触发通知操作。并且我们注意到changed 属性被初始化为false,这将意味着如果我们不主动设置changed属性为true,将不会有任何变化,也就是说根本起不到“通知”作用。因此,设置changed属性的值是我们应用jdk observer 设计模式的关键所在。那么如何才能设置changed属性呢?从源码可以看出,唯一的入口是通过setChanged()。下面我们分析一下changed属性及相关的方法setChanged()和clearChanged()。
4. Observable类的分析
Observable#changed属性的初始值为false,这很容易理解,不再详细陈述。细心的读者可能会注意到跟changed属性有关的两个方法setChanged()和clearChanged(),它们的修饰符都是protected。想强调的是,是protected,而不是public。但这样是否有其必要性和合理性?答案是肯定的。在前面的分析中,我已经提到,setChanged()方法是设置changed的唯一入口,它的修饰符定义为protected,就意味着通过定义Observable的对象,再设置changed属性将变得不可能。从这个意义上说,要想应用observer设计模式,必须继承Observable类方可。关于这一点,下文还会提及。但是,为什么不能定义成public?这似乎难以理解。因为定义成public,我们不就可以很方便地设置changed属性的值吗?为了弄清楚这个问题,我们还是看一下Observable里的相关的代码:
//……省略……
public void notifyObservers(Object arg) {
//……省略……
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}

这段代码表达的意思是说找出所有已注册的Observer,再逐个进行“通知”,通过调用Observer#update(Observable,Object)方法进行通知。我们看到,update 第一个参数是this,我们同时还必须注意到,这段代码是Observable类里的代码。这就相当于是在一再强调,发出“通知”的,必须是observable自己(Observable类或者其派生类),其它任何类都不行。这就意味着我们的observable类继承Observable类是必要的,因为如果不继承,而采用组合的话,将无法保证能传递好this。换句话说,采用组合的方式使用Observable类,将变得几乎没有任何意义。同时,修饰符定义为protected,可以确保是在Obsrvable里进行触发通知的,不会在其它任何地方进行通知,这显得内敛性很强。如果将setChanged()修饰符定义为public,将无法保证正确“传递this”的硬性要求,这不符合“只有observalbe才能直接或间接通知observer”这一observable设计模式的硬性要求。由此我们可见一斑,jdk的很多理念的思想性是多么的强。
5. 解决使用observer设计模式存在的困难
借助adapter设计模式(详见本人发表的adapter设计模式相关文章)和java支持多接口特性基本可以解决“多继承”问题。基本思想是结合继承/实现和组合来达到效果。在上面的分析中,我们已经知道,Observable类必须继承使用,不能组合使用,因此我们只需要将需扮演成observerable角色的类装扮成adapter角色,将该类原继承的类装扮成adaptee角色即可。示例代码如下:
//欲充当observable角色的类的原来的代码:
public class MyObject extends BaseObject {
public MyObject() {
public void method1(){}
}

}

//充当observable角色后的代码:
public class MyObject extends Observable {
private BaseObject baseObject = null;
public MyObject(BaseObject baseObject) {
this.baseObject = baseObject;
}
}
6. 注意事项:
如果上例中的BaseObject也用到需要传递“this”的方法,那么上面的组合使用方法将有可能失效。这种情况是最糟糕的情况。此时可以考虑在BaseObject类这些“瓶颈”地方尽量采用接口代替类(包括抽象类)来解决。

关于作者
原名 顾乃忠, 现为广州一IT公司的高级技术人员,2001年大学毕业。专注JAVA和C++相关技术的学习和研究。您可以通过 gunzh@126.com 与 gunzh(beyondsoul) 联系。

(转载文章请保留出处:北天JAVA技术网(www.java114.com))
 
更多精彩文章:
Ioc模式解析
IoC 容器和DependencyInjection 模式
Spring中IOC的实现
使用Java的动态代理技术实现对象适配器模式
深入浅出Java设计模式之迭代器模式
深入浅出Java设计模式之迭代器模式
 
最近评论:
        
鍥炲
        
那个雨天的想法!
wow gold,wow power leveling.wow power leveling,wow power leveling, max(3791)
        
那天的情景!
Maple Story mesos,MapleStory mesos,ms mesos,mesos,SilkRoad Gold, max(1194)
        
轻轻走过你的窗前!
world of warcraft gold,cheap world of warcraft gold,warcraft gold,world of warcraft gold,cheap world of warcraft gold,warcraft gold max(8253)
        
不在的哪天!
final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,final fantasy xi gil, max(7211)
        
没有情人的情人节!
wow gold,wow power leveling.wow power leveling,wow power leveling, max(4173)
        
回复:JDK Observer设计模式之研究
guild wars gold gw gold Maple Story Mesos Maple Mesos cheap guild wars gold guild wars money buy guild wars gold gw money cheap guild wars money cheap gw money MapleStory Mesos Maple Story Meso buy Maple Story Mesos cheap Maple Story Mesos buy Maple Meso cheap MapleStory Mesos cheap Maple Story Meso
        
我想告诉你!
final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,world of warcraft gold,cheap world of warcraft gold max(7469)
        
我想告诉你!
final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,world of warcraft gold,cheap world of warcraft gold max(411)
        
我想告诉你!
ffxi gil,ffxi gil,ffxi gil,final fantasy xi gil, max(3326)
        
标 题:   
内 容:   
 
                                  
 
免责声明:该文章由网友发表,如果对您造成侵权,请联系站长

首页 - 承接项目 - 网站地图 - 联系我们 -
版权所有北天JAVA技术工作室 ICP证号:粤ICP备06079815号