JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型

上传人:206****923 文档编号:91041885 上传时间:2019-06-21 格式:DOC 页数:18 大小:307KB
返回 下载 相关 举报
JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型_第1页
第1页 / 共18页
JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型_第2页
第2页 / 共18页
JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型_第3页
第3页 / 共18页
JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型_第4页
第4页 / 共18页
JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型_第5页
第5页 / 共18页
点击查看更多>>
资源描述

《JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型》由会员分享,可在线阅读,更多相关《JAVA观察者模式详解包含观察者模式JDK的漏洞以及事件驱动模型(18页珍藏版)》请在金锄头文库上搜索。

1、本章我们讨论一个除前面的单例以及代理模式之外,一个WEB项目中有可能用到的设计模式,即观察者模式。说起观察者模式,LZ还是非常激动的,当初这算是第一个让LZ感受到设计模式强大的家伙。当初LZ要做一个小型WEB项目,要上传给服务器文件,一个需求就是要显示上传进度,LZ就是用这个模式解决了当时的问题,那时LZ接触JAVA刚几个月,比葫芦画瓢的用了观察者模式。现在谈及观察者模式,能用到的地方就相对较多了,通常意义上如果一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式。下面LZ先给出观察者模式标准版的定义,引自百度百科。定义:观察者模式(有时又被称为发布-订阅模式、模型-

2、视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。上面的定义当中,主要有这样几个意思,首先是有一个目标的物件,通俗点讲就是一个类,它管理了所有依赖于它的观察者物件,或者通俗点说是观察者类,并在它自己状态发生变化时,主动发出通知。简单点概括成通俗的话来说,就是一个类管理着所有依赖于它的观察者类,并且它状态变化时会主动给这些依赖它的类发出通知。那么我们针对上面的描述给出观察者模式的类图,百度百科没有给出观察者模式的类图

3、,这里LZ自己使用工具给各位画一个。可以看到,我们的被观察者类Observable只关联了一个Observer的列表,然后在自己状态变化时,使用notifyObservers方法通知这些Observer,具体这些Observer都是什么,被观察者是不关心也不需要知道的。上面就将观察者和被观察者二者的耦合度降到很低了,而我们具体的观察者是必须要知道自己观察的是谁,所以它依赖于被观察者。下面LZ给写出一个很简单的观察者模式,来使用JAVA代码简单诠释一下上面的类图。首先是观察者接口。packagenet;/这个接口是为了提供一个统一的观察者做出相应行为的方法publicinterfaceObser

4、vervoidupdate(Observableo);再者是具体的观察者。packagenet;publicclassConcreteObserver1implementsObserverpublicvoidupdate(Observableo)System.out.println(观察者1观察到+o.getClass().getSimpleName()+发生变化);System.out.println(观察者1做出相应);packagenet;publicclassConcreteObserver2implementsObserverpublicvoidupdate(Observableo)

5、System.out.println(观察者2观察到+o.getClass().getSimpleName()+发生变化);System.out.println(观察者2做出相应);下面是被观察者,它有一个观察者的列表,并且有一个通知所有观察者的方法,通知的方式就是调用观察者通用的接口行为update方法。下面我们看它的代码。packagenet;importjava.util.ArrayList;importjava.util.List;publicclassObservableListobservers=newArrayList();publicvoidaddObserver(Observ

6、ero)observers.add(o);publicvoidchanged()System.out.println(我是被观察者,我已经发生变化了);notifyObservers();/通知观察自己的所有观察者publicvoidnotifyObservers()for(Observerobserver:observers)observer.update(this);这里面很简单,新增两个方法,一个是为了改变自己的同时通知观察者们,一个是为了给客户端一个添加观察者的公共接口。下面我们使用客户端调用一下,看一下客户端如何操作。packagenet;publicclassClientpubli

7、cstaticvoidmain(Stringargs)throwsExceptionObservableobservable=newObservable();observable.addObserver(newConcreteObserver1();observable.addObserver(newConcreteObserver2();observable.changed();运行结果如下。可以看到我们在操作被观察者时,只要调用changed方法,观察者们就会做出相应的动作,而添加观察者这个行为算是准备阶段,将具体的观察者关联到被观察者上面去。缪买网 下面LZ给出一个有实际意义的例子,比如

8、我们经常看的小说网站,都有这样的功能,就是读者可以订阅作者,这当中就有明显的观察者模式案例,就是作者和读者。他们的关系是一旦读者关注了一个作者,那么这个作者一旦有什么新书,就都要通知读者们,这明显是一个观察者模式的案例,所以我们可以使用观察者模式解决。由于JDK中为了方便开发人员,已经写好了现成的观察者接口和被观察者类,下面LZ先给出JDK中现成的观察者和被观察者代码,外加自己的一点解释,来帮助一些读者对JDK中对观察者模式的支持熟悉一下。先来观察者接口。/观察者接口,每一个观察者都必须实现这个接口publicinterfaceObserver/这个方法是观察者在观察对象产生变化时所做的响应动

9、作,从中传入了观察的对象和一个预留参数voidupdate(Observableo,Objectarg);下面是被观察者类。importjava.util.Vector;/被观察者类publicclassObservable/这是一个改变标识,来标记该被观察者有没有改变privatebooleanchanged=false;/持有一个观察者列表privateVectorobs;publicObservable()obs=newVector();/添加观察者,添加时会去重publicsynchronizedvoidaddObserver(Observero)if(o=null)thrownewN

10、ullPointerException();if(!obs.contains(o)obs.addElement(o);/删除观察者publicsynchronizedvoiddeleteObserver(Observero)obs.removeElement(o);/notifyObservers(Objectarg)的重载方法publicvoidnotifyObservers()notifyObservers(null);/通知所有观察者,被观察者改变了,你可以执行你的update方法了。publicvoidnotifyObservers(Objectarg)/一个临时的数组,用于并发访问被

11、观察者时,留住观察者列表的当前状态,这种处理方式其实也算是一种设计模式,即备忘录模式。ObjectarrLocal;/注意这个同步块,它表示在获取观察者列表时,该对象是被锁定的/也就是说,在我获取到观察者列表之前,不允许其他线程改变观察者列表synchronized(this)/如果没变化直接返回if(!changed)return;/这里将当前的观察者列表放入临时数组arrLocal=obs.toArray();/将改变标识重新置回未改变clearChanged();/注意这个for循环没有在同步块,此时已经释放了被观察者的锁,其他线程可以改变观察者列表/但是这并不影响我们当前进行的操作,因

12、为我们已经将观察者列表复制到临时数组/在通知时我们只通知数组中的观察者,当前删除和添加观察者,都不会影响我们通知的对象for(inti=arrLocal.length-1;i=0;i-)(Observer)arrLocali).update(this,arg);/删除所有观察者publicsynchronizedvoiddeleteObservers()obs.removeAllElements();/标识被观察者被改变过了protectedsynchronizedvoidsetChanged()changed=true;/标识被观察者没改变protectedsynchronizedvoidc

13、learChanged()changed=false;/返回被观察者是否改变publicsynchronizedbooleanhasChanged()returnchanged;/返回观察者数量publicsynchronizedintcountObservers()returnobs.size();被观察者除了一点同步的地方需要特殊解释一下,其余的相信各位都能看明白各个方法的用途。其实上述JDK的类是有漏洞的,或者说,在我们使用观察者模式时要注意一个问题,就是notifyObservers这个方法中的这一段代码。for(inti=arrLocal.length-1;i=0;i-)(Obser

14、ver)arrLocali).update(this,arg);在循环遍历观察者让观察者做出响应时,JDK没有去抓取update方法中的异常,所以假设在这过程中有一个update方法抛出了异常,那么剩下还未通知的观察者就全都通知不到了,所以LZ个人比较疑惑这样的用意(LZ无法想象JAVA类库的制造者没考虑到这个问题),是sun当时真的忘了考虑这一点,还是另有它意?当然各位读者如果有自己的见解可以告知LZ,不过LZ认为,不管是sun如此做是别有用意,还是真的欠考虑,我们都要注意在update方法里一定要处理好异常,个人觉得JDK中比较保险的做法还是如下这样。for(inti=arrLocal.l

15、ength-1;i=0;i-)try(Observer)arrLocali).update(this,arg);catch(Throwablee)e.printStackTrace();这样无论其中任何一个update是否成功都不会影响其余的观察者进行更新状态,我们自己比较保险的做法就是给update方法整个加上try块,或者确认不会发生运行时异常。上面LZ和各位一起分析了JDK中观察者模式的源码,下面我们就拿上述小说网的例子,做一个DEMO。首先要搞清楚在读者和作者之间是谁观察谁,很明显,应该是读者观察作者。所以作者是被观察者,读者是观察者,除了这两个类之外,我们还需要额外添加一个管理器帮我们管理下作者

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 中学教育 > 其它中学文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号