- 浏览: 464632 次
- 性别:
- 来自: 北京
最新评论
-
lm818:
最近一直在看设计模式,发现写的那本研磨真的不错,容易理解,能看 ...
大讨论:学习和应用设计模式的经验、教训、疑问等 -
yjfnwxf:
看了楼主博文,真为自己汗颜呀。。。。努力,再努力
研磨设计模式之命令模式-5 -
fengdandanweikang:
...
研磨设计模式 之 观察者模式(Observer) 1——跟着cc学设计系列 -
tiansong163:
你好,对《研磨设计模式》中UML有一个图标不知道是什么意思?希 ...
跟着cc学设计 之 研磨设计模式 目录汇总贴 -
soualliron:
国人就会溜须拍马,文章冠题“大讨论”,下面全是附会之音,无切实 ...
大讨论:学习和应用设计模式的经验、教训、疑问等
12.2 解决方案
12.2.1 观察者模式来解决
用来解决上述问题的一个合理的解决方案就是观察者模式。那么什么是观察者模式呢?
(1)观察者模式定义
(2)应用观察者模式来解决的思路
在前面描述的订阅报纸的例子里面,对于报社来说,在一开始,它并不清楚究竟有多少个订阅者会来订阅报纸,因此,报社需要维护一个订阅者的列表,这样当报社出版报纸的时候,才能够把报纸发放到所有的订阅者手中。对于订阅者来说,订阅者也就是看报的读者,多个订阅者会订阅同一份报纸。
这就出现了一个典型的一对多的对象关系,一个报纸对象,会有多个订阅者对象来订阅;当报纸出版的时候,也就是报纸对象改变的时候,需要通知所有的订阅者对象。那么怎么来建立并维护这样的关系呢?
观察者模式可以处理这种问题,观察者模式把这多个订阅者称为观察者:Observer,多个观察者观察的对象被称为目标:Subject。
一个目标可以有任意多个观察者对象,一旦目标的状态发生了改变,所有注册的观察者都会得到通知,然后各个观察者会对通知作出相应的响应,执行相应的业务功能处理,并使自己的状态和目标对象的状态保持一致。
12.2.2 模式结构和说明
观察者模式结构如图12.3所示:
图12.3 观察者模式结构示意图
Subject:
目标对象,通常具有如下功能:
- 一个目标可以被多个观察者观察
- 目标提供对观察者注册和退订的维护
- 当目标的状态发生变化时,目标负责通知所有注册的、有效的观察者
Observer:
定义观察者的接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据。
ConcreteSubject:
具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册有效的观察者,让观察者执行相应的处理。
ConcreteObserver:
观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致。
12.2.3 观察者模式示例代码
(1)先来看看目标对象的定义,示例代码如下:
/** * 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口 */ public class Subject { /** * 用来保存注册的观察者对象 */ private List<Observer> observers = new ArrayList<Observer>(); /** * 注册观察者对象 * @param observer 观察者对象 */ public void attach(Observer observer) { observers.add(observer); } /** * 删除观察者对象 * @param observer 观察者对象 */ public void detach(Observer observer) { observers.remove(observer); } /** * 通知所有注册的观察者对象 */ protected void notifyObservers() { for(Observer observer : observers){ observer.update(this); } } } |
(2)接下来看看具体的目标对象,示例代码如下:
/** * 具体的目标对象,负责把有关状态存入到相应的观察者对象, * 并在自己状态发生改变时,通知各个观察者 */ public class ConcreteSubject extends Subject { /** * 示意,目标对象的状态 */ private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; //状态发生了改变,通知各个观察者 this.notifyObservers(); } } |
(3)再来看看观察者的接口定义,示例代码如下:
/** * 观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象 */ public interface Observer { /** * 更新的接口 * @param subject 传入目标对象,好获取相应的目标对象的状态 */ public void update(Subject subject); } |
(4)接下来看看观察者的具体实现示意,示例代码如下:
/** * 具体观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致 */ public class ConcreteObserver implements Observer { /** * 示意,观者者的状态 */ private String observerState;
public void update(Subject subject) { // 具体的更新实现 //这里可能需要更新观察者的状态,使其与目标的状态保持一致 observerState = ((ConcreteSubject)subject) .getSubjectState(); } } |
12.2.4 使用观察者模式实现示例
要使用观察者模式来实现示例,那就按照前面讲述的实现思路,把报纸对象当作目标,然后订阅者当做观察者,就可以实现出来了。
使用观察者模式来实现示例的结构如图12.4所示:
图12.4 使用观察者模式来实现示例的结构示意图
还是来看看具体的代码实现。
(1)被观察的目标
在前面描述的订阅报纸的例子里面,多个订阅者都是在观察同一个报社对象,这个报社对象就是被观察的目标。这个目标的接口应该有些什么方法呢?还是从实际入手去想,看看报社都有些什么功能。报社最基本有如下的功能:
- 注册订阅者,也就是说很多个人来订报纸,报社肯定要有相应的记录才行
- 出版报纸,这个是报社的主要工作
- 发行报纸,也就是要把出版的报纸发送到订阅者手中
- 退订报纸,当订阅者不想要继续订阅了,可以取消订阅
上面这些功能是报社最最基本的功能,当然,报社还有很多别的功能,为了简单起见,这里就不再去描述了。因此报社这个目标的接口也应该实现上述功能,把他们定义在目标接口里面,示例代码如下:
/** * 目标对象,作为被观察者 */ public class Subject { /** * 用来保存注册的观察者对象,也就是报纸的订阅者 */ private List<Observer> readers = new ArrayList<Observer>();
/** * 报纸的读者需要先向报社订阅,先要注册 * @param reader 报纸的读者 * @return 是否注册成功 */ public void attach(Observer reader) { readers.add(reader); } /** * 报纸的读者可以取消订阅 * @param reader 报纸的读者 * @return 是否取消成功 */ public void detach(Observer reader) { readers.remove(reader); } /** * 当每期报纸印刷出来后,就要迅速主动的被送到读者的手中, * 相当于通知读者,让他们知道 */ protected void notifyObservers() { for(Observer reader : readers){ reader.update(this); } } } |
细心的朋友可能会发现,这个对象并没有定义出版报纸的功能,这是为了让这个对象更加通用,这个功能还是有的,放到具体报纸类里面去了,下面就来具体的看看具体的报纸类的实现。
为了演示简单,在这个实现类里面增添一个属性,用它来保存报纸的内容,然后增添一个方法来修改这个属性,修改这个属性就相当于出版了新的报纸,并且同时通知所有的订阅者。示例代码如下:
/** * 报纸对象,具体的目标实现 */ public class NewsPaper extends Subject{ /** * 报纸的具体内容 */ private String content; /** * 获取报纸的具体内容 * @return 报纸的具体内容 */ public String getContent() { return content; }
/** * 示意,设置报纸的具体内容,相当于要出版报纸了 * @param content 报纸的具体内容 */ public void setContent(String content) { this.content = content; //内容有了,说明又出报纸了,那就通知所有的读者 notifyObservers(); } } |
(2)观察者
目标定义好过后,接下来把观察者抽象出来,看看它应该具有什么功能。分析前面的描述,发现观察者只要去邮局注册了过后,就是等着接收报纸就好了,没有什么其它的功能。那么就把这个接收报纸的功能抽象成为更新的方法,从而定义出观察者接口来,示例代码如下:
/** * 观察者,比如报纸的读者 */ public interface Observer { /** * 被通知的方法 * @param subject 具体的目标对象,可以获取报纸的内容 */ public void update(Subject subject); } |
定义好了观察者的接口过后,该来想想如何实现了。具体的观察者需要实现:在收到被通知的内容后,自身如何进行相应处理的功能。为了演示的简单,收到报纸内容过后,简单的输出一下,表示收到了就行了。
定义一个简单的观察者实现,示例代码如下:
/** * 真正的读者,为了简单就描述一下姓名 */ public class Reader implements Observer{ /** * 读者的姓名 */ private String name;
public void update(Subject subject) { //这是采用拉的方式 System.out.println(name+"收到报纸了,阅读先。内容是===" +((NewsPaper)subject).getContent()); }
public String getName() { return name; } public void setName(String name) { this.name = name; } } |
(3)使用观察者模式
前面定义好了观察者和观察的目标,那么如何使用它们呢?
那就写个客户端,在客户端里面,先创建好一个报纸,作为被观察的目标,然后多创建几个读者作为观察者,当然需要把这些观察者都注册到目标里面去,接下来就可以出版报纸了,具体的示例代码如下:
public class Client { public static void main(String[] args) { //创建一个报纸,作为被观察者 NewsPaper subject = new NewsPaper(); //创建阅读者,也就是观察者 Reader reader1 = new Reader(); reader1.setName("张三");
Reader reader2 = new Reader(); reader2.setName("李四");
Reader reader3 = new Reader(); reader3.setName("王五");
//注册阅读者 subject.attach(reader1); subject.attach(reader2); subject.attach(reader3);
//要出报纸啦 subject.setContent("本期内容是观察者模式"); } } |
测试一下看看,输出结果如下:
张三收到报纸了,阅读先。内容是===本期内容是观察者模式 李四收到报纸了,阅读先。内容是===本期内容是观察者模式 王五收到报纸了,阅读先。内容是===本期内容是观察者模式 |
你还可以通过改变注册的观察者,或者是注册了又退订,来看看输出的结果。会发现没有注册或者退订的观察者是收不到报纸的。
如同前面的示例,读者和报社是一种典型的一对多的关系,一个报社有多个读者,当报社的状态发生改变,也就是出版新报纸的时候,所有注册的读者都会得到通知,然后读者会拿到报纸,读者会去阅读报纸并进行后续的操作。
发表评论
-
私塾在线推出《一案贯通GoF设计模式》项目实战
2012-10-19 22:12 20《研磨设计模式》出版以来,包括iteye上的朋友,很多人 ... -
研磨设计模式 之 组合模式(Composite) 3——跟着cc学设计系列
2012-08-22 08:50 419815.3 模式讲解 15.3.1 认识组合模式 ... -
研磨设计模式 之 组合模式(Composite) 2——跟着cc学设计系列
2012-08-20 13:53 335615.2 解决方案 15.2.1 组合模式来解决 ... -
研磨设计模式 之 组合模式(Composite) 1——跟着cc学设计系列
2012-08-20 12:17 306815.1 场景问题 15.1.1 商品类别树 ... -
研磨设计模式 之 迭代器模式(Iterator)3——跟着cc学设计系列
2012-08-19 07:07 380014.3 模式讲解 14.3.1 ... -
研磨设计模式 之 迭代器模式(Iterator)2——跟着cc学设计系列
2012-08-18 03:48 260014.2 解决方案 14.2.1 ... -
研磨设计模式 之 迭代器模式(Iterator)2——跟着cc学设计系列
2012-08-17 18:26 10614.2 解决方案 14.2.1 ... -
研磨设计模式 之 迭代器模式(Iterator)1——跟着cc学设计系列
2012-08-17 10:38 202114.1 场景问题 14.1.1 ... -
私塾在线《研磨设计模式》,精品课程上线特大惊喜
2012-08-17 10:03 6014《研磨设计模式》——跟着CC学设计,视频课程在 私塾在线 ... -
研磨设计模式 之 观察者模式(Observer) 3——跟着cc学设计系列
2012-08-16 08:51 296612.3 模式讲解 12.3.1 认识观察者模式 ... -
研磨设计模式 之 观察者模式(Observer) 1——跟着cc学设计系列
2012-08-15 07:03 210612.1 场景问题 12.1.1 订阅报纸的过程 ... -
跟着cc学设计系列 之 研磨设计模式 目录汇总贴
2012-08-14 14:49 36研磨设计模式 的 前言 ——跟着cc学 ... -
研磨设计模式 之 代理模式(Proxy)3——跟着cc学设计系列
2012-08-14 14:36 230411.3 模式讲解 11.3.1 认识代理模式 ... -
研磨设计模式 之 代理模式(Proxy)2——跟着cc学设计系列
2012-08-13 12:36 285811.2 解决方案 11.2.1 代理模式来解 ... -
研磨设计模式 之 代理模式(Proxy)1——跟着cc学设计系列
2012-08-13 12:35 214511.1 场景问题 11.1.1 访问多条数据 ... -
研磨设计模式 之 中介者模式(Mediator)3 ——跟着cc学设计系列
2012-08-11 11:50 120510.3 模式讲解 10.3.1 认识中介者模式 ... -
研磨设计模式 之 中介者模式(Mediator)2 ——跟着cc学设计系列
2012-08-09 08:23 142410.2 解决方案 10.2.1 中介者模式来 ... -
研磨设计模式 之 中介者模式(Mediator)1 ——跟着cc学设计系列
2012-08-09 08:23 146410.1 场景问题 10.1.1 ... -
研磨设计模式 之 原型模式(Prototype)3 ——跟着cc学设计系列
2012-08-08 08:14 15449.3 模式讲解 9.3.1 ... -
研磨设计模式 之 原型模式(Prototype)2 ——跟着cc学设计系列
2012-08-07 17:54 16799.2 解决方 ...
相关推荐
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
《研磨设计模式》这本书是陈臣和王斌两位作者合作的成果,专注于讲解软件设计中的模式应用。设计模式是软件工程中的一种最佳实践,它总结了在特定上下文中解决问题的常见方法,使得开发者可以复用这些解决方案,提高...
3. **行为型模式**:这一类模式主要关注对象间如何交互和分配职责,如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、命令模式(Command)、责任链模式...
《研磨设计模式》实战是IT领域中关于软件设计的一份重要资料,它主要探讨了设计模式在实际项目中的应用。设计模式是软件工程中经过长期实践总结出的通用问题解决方案,是解决常见设计问题的经验总结。这份PPT可能是...
《研磨设计模式》是一本深入探讨软件设计模式的经典书籍,源代码包含了书中所讲解的各种设计模式的实际应用示例。设计模式是软件工程中的重要概念,它们是经过反复验证、在特定情境下解决常见问题的有效解决方案。...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
这个名为“研磨设计模式视频课程PPT”的压缩包包含了一份关于23种核心设计模式的详细教学资料,旨在帮助开发者提升软件设计的效率和可维护性。下面将对这些设计模式进行深入解析。 1. **单例模式(Singleton)**:...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
比如命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy)、模板方法模式...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
第12章 观察者模式(Observer) 第13章 命令模式(Command) 第14章 迭代器模式(Iterator) 第15章 组合模式(Composite) 第16章 模板方法模式(Template Method) 第17章 策略模式(Strategy) 第18章 状态模式...
Java的研磨设计模式是将这些模式应用到Java编程中的具体体现,它能够帮助开发者编写出更加灵活、可维护和可扩展的代码。本篇文章将深入探讨设计模式的核心概念,并通过Java实例来解析这些模式。 1. 单例模式:确保...
19. **观察者模式(Observer)**:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。 20. **状态模式(State)**:允许一个对象在其内部状态改变时...
Java设计模式是软件开发中的重要...配合《研磨设计模式》这样的书籍,你可以深入学习每种模式的原理和应用场景,进一步提升自己的编程技能。在学习过程中,可以参考提供的"mydesign"源码,实践是检验理论的最好方式。
《研磨设计模式》书中的例子 --第二章:简单工厂 本质:选择实现 --第三章:外观模式(Facade) 本质:封装交互,简化调用 --第四章:适配器模式(Adapter) 本质:转换匹配,复用功能 --第五章:单例模式(Singleton) ...