Head First 设计模式学习——观察者模式
来源:互联网 发布:pc端软件下载 编辑:程序博客网 时间:2024/06/06 00:24
设计模式是进阶高级开发的必经之路。掌握设计模式,才能提升编码能力,设计出可复用、可扩展、可维护的软件系统。了解设计模式,才能更好理解开源类库的实现原理,解决问题。
观察者模式(Observer Pattern)是《Head First 设计模式》介绍的第二个模式。本文将做介绍,并介绍此模式在JDK中的应用。
定义
观察者模式定义了对象之间的一(被观察者)对多(观察者)依赖,这样一来,当一个对象(被观察者)改变状态时,它的所有依赖者(观察者)都会收到通知并自动更新。
应用场景举例
- 用户订阅报社报纸。当报社印刷新报纸(状态改变),向所有订阅用户投递报纸(推送消息)。用户可随时取消、加入订阅。
- 火车站的车次显示屏,显示车次到达发车信息。当火车数据更改时,每个显示屏都要及时更新数据。等等
分析
上述两个例子中,可以抽象出一对多的关系,比如报社对应多个用户,火车数据对应多个显示屏。用户、显示屏等是观察者,报社、火车数据是被观察者。而且观察者的数量动态变化的。有人退出,有人加入,类型不固定(有公司订阅报纸,有微信、微博发布火车时刻信息)。
如果用java实现这样的功能。自然的,可以抽象出被观察者类、观察者类。
观察者可能会观察多个数据源,一个数据源也会被不同类型的观察者关注。若在类中指定观察者、被观察者具体类型(比如报社——人,火车数据——显示屏),以后报社新增公司客户(新增观察者),火车数据新增广播平台(新增观察者),一个客户订阅另一本杂志(新增被观察者),我们就得去修改代码,糟透了。
此处,一个新的设计原则:为了交互对象之间松设计而努力诞生了。
我们应该把观察者、被观察者抽象成抽象类或者接口,定义公共的方法。让以后的观察者、被观察者实现这些接口或抽象类即可。考虑到另一个原则:针对接口编程,我们采用接口抽象。
为了能及时追踪被观察者的变化。一种方式是观察者无间断盯着被观察者,不断的问:··你到底变没变?你到底变没变?
//观察者 while(true){ //问被观察者:你到底变没变 if(观察者.hasChanged()){ //do something }}
很明显,这种方式,彼此压力都很大,不是个好设计。
另一种方式,就是当被观察者发生改变时,主动的通知观察者(调用观察者某个方法),观察者随机做出反应:
//被观察者通知观察者notifyObservers(){ //依次通知,也可以设计成单个通知 for(){ 观察者.update("喂,我变帅啦"); }}//回执result(观察者 观察者1,String info){ System.out.println(观察者1.class.getName()+"发来消息:"+info)}-------------------------------------------//观察者update(String info){ System.out.println("收到消息,被观察者:"+info); //甚至可以设置个回执,告诉被观察者,你的消息我收到了 //传入观察者自己,好让被观察者知道谁给他发的回执 被观察者.result(观察者,"我收到你的消息了");}
这才是我们想要的。再加上新增、删除观察者功能,我们基本上就实现了观察者模式设计了。
代码
根据面向接口编程原则,把观察者、被观察者抽象成接口:
//被观察者Observered接口public interface Observered { //新增一个观察者 void addObserver(Observer observer); //删除某个观察者 void removeObserver(Observer observer); //通知所有观察者 void notifyObserver();}//-----------------------------------------//观察者Observer接口public interface Observer { //被观察者调用。 //@param observered 被观察者(有可能当前观察者关注了多个数据源) //@param obj 传入的数据。自定义类型,此处用Object void update(Observered observered,Object obj );}
接下来就是具体的实现类。此处我们安排三个观察者,两个被观察者。场景: Aboy
、Bboy
在淘宝上买了东西,淘宝Taobao
需要推送发货信息给Aboy
和Bboy
,Aboy
和Cgirl
关注了一个公众号WeChatPublicSignal
(姑且这么叫吧),公众号会推送文章给这俩人。
首先两个被观察者:Taobao
和WeChatPublicSignal
class Taobao implements Observered{ //用LinkedList<E>或其他结构 List<Observer> observerList = new ArrayList<Observer>(); @Override public void addObserver(Observer observer) { //添加一个观察者 observerList.add(observer); } @Override public void removeObserver(Observer observer) { observerList.remove(observer); //移除一个观察者 } @Override public void notifyObserver() { //遍历,通知所有观察者并发送消息 for (Observer observer : observerList) { System.out.println("Taobao说:我正在发数据给"+observer.getSimpleName().getName()); //此处的数据参数可以灵活设计 observer.update(this, "你买的娃娃已经发货啦___"); } }}class Taobao implements Observered{//其他代码同Taobao,略,只改动发送的数据 observer.update(this, "咪蒙说:外国人那么大,我想去看看");}
三个观察者Aboy、Bboy和Cgirl
//实现观察者接口class Aboy implements Observer{ @Override public void update(Observered observered, Object obj) { System.out.println("Aboy------说:我接收到--"+observered.getClass().getSimpleName()+"--发来数据: "+obj); }}//Bboy、Cgril同Aboy,略
测试:
public static void main(String[] args) { //实例化观察者 Observer aboy = new Aboy(); Observer bboy = new Bboy(); Observer cgirl= new Cgirl(); Observered taobao = new Taobao();//被观察者Taobao //添加观察者 taobao.addObserver(aboy); taobao.addObserver(bboy); //通知观察者 taobao.notifyObserver(); //下同 Observered wechat = new WeChatPublicSignal(); wechat.addObserver(aboy); wechat.addObserver(cgirl); wechat.notifyObserver(); }
控制台输出:
Taobao----说:我正在发数据给--AboyAboy------说:我接收到--Taobao--发来数据: 你买的娃娃已经发货啦___Taobao----说:我正在发数据给--BboyBboy------说:我接收到--Taobao--发来数据: 你买的娃娃已经发货啦___WeChatPublicSignal说:我正在发数据给AboyAboy------说:我接收到--WeChatPublicSignal--发来数据: 咪蒙说:外国人那么大,我想去看看WeChatPublicSignal说:我正在发数据给CgirlCgirl-----说:我接收到--WeChatPublicSignal--发来数据: 咪蒙说:外国人那么大,我想去看看
结果符合设计。
JDK中的应用
观察者模式在JDK中有实现。java.util.Observer
就是JDK实现的观察者接口,其中就有一个update方法:
//观察者接口public interface Observer { void update(Observable o, Object arg);}
而被观察者java.util.Observable
是采用类被继承的方式设计的:
/*JDK中被观察者类的实现 *其他代码删除了,具体参考JDK源码 * @since JDK1.0 */public class Observable { private boolean changed = false; private Vector obs;//存储观察者的集合 public Observable() { obs = new Vector(); } //添加观察者 public synchronized void addObserver(Observer o) { } //删除观察者 public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } //通知观察者 public void notifyObservers(Object arg) { }}
我们设计的基本功能Observable中都有实现,且新增了不少方法。还考虑了线程安全、效率问题等。美中不足的是,你如果想使用这个类,那就得继承它,这势必会影响你的其他设计(单继承)。自己设计一个被观察者接口也很简单,随便你咯。
总结
- 观察者模式定义了对象间一对多的关系。
- 观察者和被之间用松耦合的方式连接,彼此都不知道对方是谁,只知道发出、接收数据,像网恋一样,不管对方是周杰伦还是凤姐,也能快乐的聊天恋爱。
- 可以更进一步设计数据的获取方式,推或者拉。
- Head First设计模式—观察者模式
- Head First设计模式学习笔记——观察者模式
- Head First 设计模式学习——观察者模式
- 《Head First 设计模式》模式2——观察者模式
- 《Head First设计模式》读书笔记2——观察者模式
- Head First Java设计模式——观察者模式
- Head First 设计模式——观察者模式(Observer Pattern)
- 读书笔记2:Head First设计模式——观察者模式
- 观察者模式详解——参考《Head First设计模式》
- Head First设计模式第二章——观察者模式
- 《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式
- head first设计模式学习笔记(二)——观察者模式 C++实现
- Head First 设计模式学习笔记(2)--观察者模式
- 《Head First 设计模式》学习笔记之观察者模式
- 《Head first设计模式》学习笔记 - 观察者模式
- 《Head first设计模式》学习笔记 – 观察者模式
- Head First设计模式学习笔记-------(2)观察者模式
- 学习head first 设计模式之观察者模式
- DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016错误解决方法
- 特长生模拟——买装备
- Android事件的分发机制
- python中Beautiful Soup库使用详解
- CQOI2009中位数
- Head First 设计模式学习——观察者模式
- 使用 mapreduce 求无向图的连通子图
- Spring Boot学习(五)
- SIPp 模拟注册服务器
- C# WinForm开发系列
- linux菜鸟日记
- mysql分表的3种方法
- 动态链接库vs无法启动程序 因为计算机中丢失zsKernel.dll
- WebSocket学习笔记