javaee论坛

普通会员

225649

帖子

65

回复

79

积分

楼主
发表于 2019-11-07 13:50:28 | 查看: 90 | 回复: 1

上篇我们讲解了观察者模式的一些知识,而且自定义观察者模式的经典代码,(传送们:设计模式走一遍—观察者模式(上))

这篇简单讲一下JDK自带的观察者模式实现代码。

对于观察者模式,JDK中提供了一个Observer接口(观察者),一个Observable类(主题对象)。

注:被观察者又被称为主题对象,目标对象。

具体我们来看下源码。

1.观察者接口

publicinterfaceObserver{/***Thismethodiscalledwhenevertheobserved*objectischanged.*当被观察者发生变化时,该方法将会被调用*@paramotheobservableobject.*@paramarganargumentpassedtothe<code>notifyObservers</code>*method.*/voidupdate(Observableo,Objectarg);}

该接口相当于观察者,里面有一个update(Observableo,Objectarg)方法,Observable参数是指主题对象,该参数指明该观察者是属于哪一个主题对象的。

arg参数可以是任意对象,假如主题对象在发送通知时,想要传递什么数据给观察者,那么就可以把数据对象传递给arg参数。

2.主题对象类(方法有点多,我就不放英文解释了)

//主题对象可以是接口、抽象类、具体类,我们上节说//一般采用抽象类,不过JDK这里使用的是具体类publicclassObservable{//标记主题对象的状态是否改变privatebooleanchanged=false;//存放观察者集合,之所以用Vector而不用ArrayList//主要是Vector是线程安全的privateVector<Observer>obs;publicObservable(){obs=newVector<>();}//添加一个观察者publicsynchronizedvoidaddObserver(Observero){if(o==null)thrownewNullPointerException();if(!obs.contains(o)){obs.addElement(o);}}//删除一个观察者publicsynchronizedvoiddeleteObserver(Observero){obs.removeElement(o);}//标记该对象的状态是否发送了改变protectedsynchronizedvoidsetChanged(){changed=true;}//指示该对象不会再发生改变,或者它已经通知了//所有观察者protectedsynchronizedvoidclearChanged(){changed=false;}//测试对象是否发生了改变。当且仅当在此对象最近//调用了setChange()方法publicsynchronizedbooleanhasChanged(){returnchanged;}//如果hasChanged()方法指示此对象发送了改变,//则通知所有观察者,并且调用clearChanged()方法//指示此对象不再改变publicvoidnotifyObservers(){notifyObservers(null);}//与上面没有参数的同名方法相同,只是如果这个方//法的arg参数可以接受主题对象想要传递观察者的数据对象publicvoidnotifyObservers(Objectarg){//临时保存所有观察者Object[]arrLocal;synchronized(this){if(!changed)return;arrLocal=obs.toArray();clearChanged();}for(inti=arrLocal.length-1;i>=0;i--)((Observer)arrLocal[i]).update(this,arg);}//删除所有观察者publicsynchronizedvoiddeleteObservers(){obs.removeAllElements();}//返回观察者的数量publicsynchronizedintcountObservers(){returnobs.size();}}

该具体类Observable相当于主题对象,实现的主要功能就是当自己的状态发送改变时,通知观察者,观察者再根据通知,在update方法做出相应的反应。

简单写个Demo测试下。

publicclassTest{publicstaticvoidmain(String[]args){//创建一个主题对象AnimalSubjectanimalSubject=newAnimalSubject();animalSubject.addObserver(newDogObsever());animalSubject.addObserver(newLionObsever());//状态发生改变animalSubject.setChanged();//通知观察者animalSubject.notifyObservers();}}//动物主题,弄子类方便拓展主题对象功能classAnimalSubjectextendsObservable{//不过我就不新增代码、方法了//不覆盖下的话,上面的测试调用不了setChange()方法//为了方便测试,覆盖重写下@OverrideprotectedsynchronizedvoidsetChanged(){super.setChanged();}}classDogObseverimplementsObserver{@Overridepublicvoidupdate(Observableo,Objectarg){System.out.println("收到通知,小狗观察者正在做出相应处理");}}classLionObseverimplementsObserver{@Overridepublicvoidupdate(Observableo,Objectarg){System.out.println("收到通知,狮子观察者正在做出相应处理");}}

打印结果

收到通知,狮子观察者正在做出相应处理收到通知,小狗观察者正在做出相应处理

从上面的代码中我们可以发现JDk内置的观察者模式中的主题对象是一个具体类,而不是一个抽象类或接口,而且setChange()方法还被保护起来了(被定义为protected),这就意味着,要在别的类中调用该方法,那么我们必须继承在子类中重写覆盖该方法。显然,我觉得这很不友好…

可能这也是JDK内置的观察者模式很少被拿来使用的原因吧,一般都是自己来自定义观察者模式。

希望大家能够动手写一下这些代码,可能会碰到一些你没想到的问题。

关注公我的众号:苦逼的码农,获取更多原创文章,后台回复礼包送你一份时下热门的资源大礼包。同时也感谢把文章介绍给更多需要的人


普通会员

0

帖子

71

回复

78

积分
沙发
发表于 2019-11-12 19:17:06

如果这就是爱,再转身的时候就该留下

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017