WX搜索:程序员的个人修养查看更多观察者模式(Observer)观察者模式是JDK中使用最多的模式之一,非常好用。观察者模式提供了一种将主体和观察者松散耦合的对象设计。DefiningObserver模式定义了对象之间的一对多依赖关系,这样当一个对象改变状态时,它的所有依赖对象都会收到通知并自动更新。一对多:一个主体可以对应多个观察者。依赖性:观察者是主体的依赖者。当数据发生变化和更新时,它可以获得比让许多对象控制相同数据更清晰的OO设计。例如报社的经营模式:报社的业务是出版报纸。订阅一份报纸,只要他们有一篇新论文发表,就会发给你。只要您是他们的订户,您将始终收到新论文。当你不想再看报纸时,取消订阅,他们就不会送新报纸了。只要报社还在营业,总会有人(或单位)订阅或退订。发布者+订阅者=观察者模型房产中介机构会通过自己的渠道获取大量房产信息。需要买房的人会去中介公司或者网上登记购房需求。当中介公司有合适的房源时,会通知购房者。购房者可以获得最新的楼盘信息。中介公司+购房者=观察者模式类图代码实现包com.study.design.Observer.custom;/***观察者实现类*/publicclassConcreteObserverimplementsObserver{//本地存储主题对象,方便后续取消订阅,如果不需要,则不需要保存privateSubject主题;publicConcreteObserver(Subjectsubject){this.subject=subject;//订阅主题subject.registerObserver(this);}@Overridepublicvoidupdate(intstat){System.out.println("stateupdate:"+stat);}}packagecom.study.design.Observer.custom;importjava.util.ArrayList;importjava.util.List;publicclassConcreteSubjectimplementsSubject{Listobservers;内部统计;publicConcreteSubject(){observers=newArrayList();}@OverridepublicvoidregisterObserver(Observero){observers.add(o);}@OverridepublicvoidremoveObserver(Observero){inti=observers.索引(o);如果(我>0){观察者。删除(我);}}@OverridepublicvoidnotifyObservers(intstat){for(Observerobserver:observers){observer.update(stat);}}@OverridepublicvoidupdateStat(intstat){this.stat=stat;通知观察者(统计);}}packagecom.study.design.Observer.custom;/***观察者界面*/publicinterfaceObserver{voidupdate(intstat);}packagecom.study.design.Observer.custom;/***主题界面*/publicinterfaceSubject{voidregisterObserver(Observero);voidremoveObserver(Observero);voidnotifyObservers(intstat);voidupdateStat(intstat);}packagecom.study.design.Observer.custom;publicclassCustomTest{publicstaticvoidmain(String[]args){//创建主题Subjectsubject=newConcreteSubject();//创建观察者对象Observerobserver=newConcreteObserver(subject);//主题状态更新subject.updateStat(1);}}上面代码展示了“推送”模式,即主题数据更新后,主题对象将最新的数据推送给观察者数据也可以由观察者主动从对象中拉取,称为“拉取”模式。在实际开发过程中,如果一个topic负责多条数据,每个观察者只订阅其中的一部分,那么pull模式比较适合。观察者主动从主题中拉取需要的数据,主题只需要为每条数据提供一个get方法即可,如果以后主题扩展功能增加了更多的数据,那么主题就不需要了为每个更新的Observer调用需要改变自己以提供更多的getter方法。Java的内置观察者模式支持这两种模式。Java的内置观察者模式观察者模式内置于JavaAPI中。java.util包中包含了最基本的Observer接口和Observable类,和我们的Subject接口和Observer接口非常相似。Observer接口和Observable类一起使用更方便,因为很多功能都已经提前准备好了。你甚至可以使用推(push)或拉(pull)来传输数据。packagejava.util;/***主题类*虽然定义为类而不是之前的接口类型,*但是更新状态的setChanged和setChanged方法定义为保护类型*所以,在实际开发中,它还是需要实现一个子类继承自Observable*/publicclassObservable{/**Themestatus**/privatebooleanchanged=false;/**存储观察者对象**/privateVectorobs;/**构造函数**/publicObservable(){obs=newVector<>();}/**注册观察者对象**/publicsynchronizedvoidaddObserver(Observero){if(o==null)thrownewNullPointerException();如果(!obs.contains(o)){obs.addElement(o);}}/**移除指定的观察者对象**/publicsynchronizedvoiddeleteObserver(Observero){obs.removeElement(o);}/**Notification所有观察者对象,状态已经更新,还没有传输数据**/publicvoidnotifyObservers(){notifyObservers(null);}/**通知所有观察者对象,状态已经更新,可以传输任何类型的数据**/publicvoidnotifyObservers(Objectarg){Object[]arrLocal;同步(这){如果(!改变)返回;arrLocal=obs.toArray();清除更改();}for(inti=arrLocal.length-1;i>=0;i--)((Observer)arrLocal[i]).update(this,arg);}/**移除所有观察者对象**/publicsynchronizedvoiddeleteObservers(){obs.removeAllElements();}/***更新状态*在发送通知之前,需要调用该方法来标记状态已经改变,否则通知被释放*/protectedsynchronizedvoidsetChanged(){changed=true;}/***恢复状态*通知发送后,需要恢复状态标记*/protectedsynchronizedvoidclearChanged(){changed=false;}/**获取状态更新**/publicsynchronizedbooleanhasChanged(){returnchanged;}/**注册观察者数量**/publicsynchronizedintcountObservers(){returnobs.size();}}packagejava.util;/***观察者接口,通过观察者接口实现业务处理*/publicinterfaceObserver{/***接收主题数据更新通知*@paramo:主题对象@@paramarg:数据对象,根据业务场景,可能为null*/voidupdate(Observableo,Objectarg);}推送模式实现代码:packagecom.study.design.Observer.jdk.push;importjava.util.Observable;publicclassPushObservableextendsObservable{@OverrideprotectedsynchronizedvoidsetChanged(){super.setChanged();}}packagecom.study.design.Observer.jdk.push;importjava.util.Observable;importjava.util.Observer;publicclassPushObserverimplementsObserver{@Overridepublicvoidupdate(Observableo,Objectarg){System.out.println("更新:"+arg.toString());}}packagecom.study.design.Observer.jdk.push;publicclassPushTest{publicstaticvoidmain(String[]args){//创建观察对象PushObserverconcreteObserver=newPushObserver();//创建主题对象PushObservableobservable=newPushObservable();//订阅observable.addObserver(concreteObserver);//更新主题状态observable.setChanged();//向观察者发送通知Observable.notifyObservers("PushTestchange");}}拉模型实践步骤:packagecom.study.design.Observer.jdk.pull;importjava.util.Observable;publicclassPullObservableextendsObservable{privateStringdata;@OverrideprotectedsynchronizedvoidsetChanged(){super.setChanged();}publicStringgetData(){返回数据;}publicvoidsetData(Stringdata){this.data=data;}}packagecom.study.design.Observer.jdk.pull;importjava.util.Observable;importjava.util.Observer;publicclassPullObserverimplementsObserver{@Overridepublicvoidupdate(Observableo,Objectarg){if(oinstanceofPullObservable){PullObservablepullObservable=(PullObservable)o;System.out.println("更新:"+pullObservable.getData());}}}packagecom.study.design.Observer.jdk.pull;publicclassPullTest{publicstaticvoidmain(String[]args){//创建观察者对比PullObserverconcreteObserver=newPullObserver();//创建主题对象PullObservableobservable=newPullObservable();//订阅observable.addObserver(concreteObserver);//更新数据observable.setData("PullTestchange");//更新主题状态observable.setChanged();//向观察者发送通知observable.notifyObservers();}}注意:当有多个观察者,多次执行时,调用观察者的顺序不一致关系主题(即observable)使用公共接口来更新观察者。观察者和可观察对象以松散耦合的方式组合在一起。observable不知道观察者的细节,只知道观察者实现了观察者当接口使用这种模式时,你可以从observable中推送或拉取数据当有多个观察者时,你不能依赖特定的通知顺序是意识到java.util.Observable实现的一些问题WX搜索:程序人员个人修养查看更多