Java观察者模式 java.util.Observable 与 java.util.Observer 的理解

来源:互联网 发布:淘宝宝贝浏览量怎么看 编辑:程序博客网 时间:2024/05/29 07:14

转载地址:http://kentkwan.iteye.com/blog/739516


Part I

JDK1.2后,Java提供了对观察者模式的支持接口和实现类。

其中接口 java.util.Observer 用来指定观察者,观察者必须实现 void update(Observable o, Object arg) 方法。

而 java.util.Observable 用来指定观察物(被观察者、可被观察的),并且提供了一系列的方法。读者可以很轻易的使用这个接口和实现类来实现观察者模式。

 

Part II

java.util.Observer 只有一个简单的方法 void update(Observable o, Object arg)

其中,参数 Observable o 用于指定触发 update 方法的对象, Object arg 用于指定触发 update 方法时候的附加参数。

如果有桌面应用开发的读者应该很了解,这跟事件处理机制是完全一样的,其中 Observable o 可被看作事件源。 Object arg 可被看作消息。

 

Part III

说了那么多,我们还是动手写个例子吧。这里我们以读者订阅杂志为例子。

package com.gzmu.observer.observable;import java.util.Observable;public class Publisher extends Observable {private String magazineName;public String getMagazineName() {return magazineName;    }public void publish(String magazineName) {this.magazineName = magazineName;        setChanged();        notifyObservers(this);    }}

package com.gzmu.observer.observer;import java.util.Observable;import java.util.Observer;import com.gzmu.observer.observable.Publisher;public class Reader implements Observer {    @Overridepublic void update(Observable o, Object arg) {        Publisher p = (Publisher) o;        System.out.println("我要订阅" + p.getMagazineName());    }}

package com.gzmu.observer.test;import org.junit.Test;import com.gzmu.observer.observable.Publisher;public class TestCase {    @Testpublic void register() {        Publisher publisher = new Publisher();        publisher.publish("Kent.Kuan的技术空间");    }}

这里很清楚的看到,当出版社出版杂志的时候,会主动的告知读者,读者就会订阅杂志,这也是一种主动推送的模式。

 

Part IV

这里大家会发现,调用 notifyObservers() 的时候,为什么传进当前对象 this 呢?而这个 this, 我们在读者那也没用到啊。这个问题曾经也让我觉得很苦恼,之前我也不清楚为什么观察者要拿到被观察对象的引用,但是,我们看看下面这个例子。

首先我们引用一个新的类:

package com.gzmu.observer.observable;import java.util.Observable;public class TVStation extends Observable {private String programmeName;public void play(String programmeName) {this.programmeName = programmeName;        setChanged();        notifyObservers(this);    }public String getProgrammeName() {return programmeName;    }}

然后修改Reader和TestCase:

package com.gzmu.observer.observer;import java.util.Observable;import java.util.Observer;import com.gzmu.observer.observable.Publisher;import com.gzmu.observer.observable.TVStation;public class Reader implements Observer {    @Overridepublic void update(Observable o, Object arg) {if (o instanceof Publisher) {            Publisher p = (Publisher) o;            System.out.println("我要订阅" + p.getMagazineName());        }if (o instanceof TVStation) {            TVStation t = (TVStation) o;            System.out.println("我要收看" + t.getProgrammeName());        }    }}

package com.gzmu.observer.test;import org.junit.Test;import com.gzmu.observer.observable.Publisher;import com.gzmu.observer.observable.TVStation;import com.gzmu.observer.observer.Reader;public class TestCase {    @Testpublic void register() {        Reader reader = new Reader();        Publisher publisher = new Publisher();        publisher.addObserver(reader);        TVStation tvStation = new TVStation();        tvStation.addObserver(reader);        publisher.publish("Kent.Kwan的技术空间");        tvStation.play("色戒");    }}

最后我们可以看到,同一个观察者其实是可以注册到不同的被观察者上面的,而传过来的 Oberverable o 其实可以用来检验到底是谁发过来的消息。

除此以外,我们还可以在接受到消息之后,进行撤销观察的工作。

package com.gzmu.observer.observer;import java.util.Observable;import java.util.Observer;import com.gzmu.observer.observable.Publisher;import com.gzmu.observer.observable.TVStation;public class Reader implements Observer {    @Overridepublic void update(Observable o, Object arg) {if (o instanceof Publisher) {            Publisher p = (Publisher) o;            p.deleteObserver(this);            System.out.println("我要订阅" + p.getMagazineName());        }if (o instanceof TVStation) {            TVStation t = (TVStation) o;            System.out.println("我要收看" + t.getProgrammeName());        }    }}

通过 deleteObserver() 方法就可以撤销观察出版社对象。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 父亲对母亲家暴怎么办 摊上家暴的父亲怎么办 家暴警察不处理怎么办 父亲把母亲打了怎么办 u盘的文件打不开怎么办 头撞墙起包了怎么办 儿童头撞墙起包怎么办 头撞墙了鼓包了怎么办 北京65岁老年证怎么办 怎么办65岁免费乘车卡 5个月小孩晚上哭怎么办 婴儿要含奶头睡怎么办 我把输入法删了怎么办 头发干枯毛躁怎么办用什么洗发水 落枕后脖子歪了怎么办 睡觉睡得脖子疼怎么办? 婴儿脖子睡歪了怎么办 怀孕8个月肚皮痒怎么办 怀孕大阴唇肿了怎么办 孕妇肚皮撑的疼怎么办 我大阴唇特别长怎么办 切完洋葱辣眼睛怎么办 下昆山车没刷卡怎么办 高德地图用不了怎么办 玩游戏老是闪退怎么办 苹果平板电脑闪退怎么办 钉钉忘记打卡了怎么办 钉钉手机号换了怎么办 玖富叮当贷逾期怎么办 玖富超能怎么办现金贷 包包的油边开裂怎么办 lv包包油边开裂怎么办 lv钱包油边开裂怎么办 德运奶粉没勺子怎么办 音响坏了没声音怎么办 6s蓝牙无法配对怎么办 魅族耳机进水了怎么办 苹果6耳机进水了怎么办 耳机内部线坏了怎么办 酷狗m1开不开机怎么办 小米2s蓝牙坏了怎么办