设计模式之观察者模式(Observer Pattern)
一.什么是观察者模式?
把现实世界中的报纸与订阅者的关系抽象出来就是观察者模式,一种报纸对应多个订阅者,订阅者可以随时解除订阅,未订阅的读者也可以随时开始订阅。一旦有新报纸发布,所有的订阅者都会收到新内容。
在观察者模式中,报纸叫做主题Subject,订阅者叫做观察者Observer,一个Subject可以被多个Observer关注,Observer可以随时解除关注,新的Observer也可以随时关注Subject。Subject内容发生改变时,会通知所有的Observer。
二.举个例子
很多网络游戏中都有答题活动,所有参与答题活动的玩家都会同时收到题目信息(延迟忽略不计),未参与活动的玩家可以中途加入,正在答题的玩家也可以随时退出。
在此例中,游戏服务器就是“一”,玩家是“多”,题目信息就是在它们之间传递的消息。
怎样才能设计出满足以上要求的类?不妨试试观察者模式。
首先,定义Subject抽象类:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package ObserverPattern;import java.util.ArrayList;/** * @author ayqy * 定义Subject抽象类 * */public abstract class Subject { ArrayList<Observer> observers = new ArrayList<Observer>();//观察者列表 /** * 注册主题 * @param o 申请注册该主题的Observer */ public void registSubject(Observer o) { observers.add(o); } /** * 删除主题 * @param o */ public void reomveSubject(Observer o) { int index = observers.indexOf(o); observers.remove(index); } /** * 通知所有观察者 * @param arg 该Subject想要传递给Observers的数据 */ public void notifyObservers(Object arg) { for(Observer o : observers) o.update(this, arg); }} |
注意,这里用了抽象类而没有用接口,为什么?
因为Subject的行为是fixed的,并不需要由子类来扩展。
-------
类似的,我们定义Observer抽象类:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
package ObserverPattern;/** * @author ayqy * 定义Observer抽象类 * */public abstract class Observer { Subject subject = null;//定义该Observer所关注的Subject public abstract void update(Subject subject, Object arg);//定义Observer的更新接口} |
-------
下面开始实现我们的自定义Subject——GameServer:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package ObserverPattern;/** * @author ayqy * 定义GameServer类,继承自Subject基类,负责发布题目 * */public class GameServer extends Subject{ Question ques;//定义题目 public Question getQues() { return ques; } public void setQues(Question q) { this.ques = q; super.notifyObservers(ques);//调用父类方法通知所有Observer }} |
P.S.GameServer类的成员变量Question是对题目信息的简单封装,Question类包含题号no与题目内容content两部分定义,以及一个toString方法,返回题目描述信息
-------
再实现我们的自定义Observer——Player:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package ObserverPattern;/** * @author ayqy * 定义PlayerA,继承自Observer基类,负责接收新题目 * */public class PlayerA extends Observer{ public PlayerA(Subject sub) { subject = sub; } @Override public void update(Subject subject, Object arg) { Question q = (Question)arg; System.out.println("PlayerA received " + q.toString()); } } |
P.S.为了使类层次更加清晰,此处并没有定义Player基类
很容易复制粘贴得到PlayerB与PlayerC,不再赘述
至此,我们的模拟答题活动准备工作已经结束了,下面我们需要定义一个测试类来展示观察者模式的魅力。
三.效果示例
定义如下Test类:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package ObserverPattern;/** * @author ayqy * 实现一个测试类,模拟网络游戏答题活动(游戏服务器按时更新题目信息并通知所有参与答题的玩家) * */public class Test { public static void main(String[] args) { System.out.println("答题活动即将开始。。"); //创建服务器 GameServer gs = new GameServer(); //创建玩家ABC Observer playerA = new PlayerA(gs); Observer playerB = new PlayerB(gs); Observer playerC = new PlayerC(gs); //为AB注册Subject,C对答题不感兴趣,拒绝注册 gs.registSubject(playerA); gs.registSubject(playerB); System.out.println("玩家AB成功参与答题活动。。"); System.out.println("答题活动正式开始。。"); gs.setQues(new Question(1, "第一题")); gs.setQues(new Question(2, "第二题")); System.out.println("玩家A不想玩了,退出答题活动。。"); gs.reomveSubject(playerA); gs.setQues(new Question(3, "第三题")); System.out.println("玩家C想中途加入活动"); gs.registSubject(playerC); gs.setQues(new Question(4, "第四题")); System.out.println("答题活动结束。。"); }} |
结果示例:

四.总结
从上面的例子可以看出观察者模式的特点:
1.利用观察者模式可以轻易地建立对象之间“一对多”的依赖关系
2.利用观察者模式的机制可以很容易的实现这种依赖关系的动态维护
<声明>作者水平有限 错误在所难免 欢迎指正</声明>
<邮箱>835412398@qq.com 交流方可进步</邮箱>
设计模式之观察者模式(Observer Pattern)的更多相关文章
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 二十四种设计模式:观察者模式(Observer Pattern)
观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...
- [设计模式] 19 观察者模式 Observer Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...
- c#设计模式之观察者模式(Observer Pattern)
场景出发 一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了 这个过程,如果用面向对象语言来描述,简单莫过于下: public class Cat { ...
- 设计模式之观察者模式(Observer pattern)
最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...
- 设计模式九: 观察者模式(Observer Pattern)
简介 观察者属于行为型模式的一种, 又叫发布-订阅模式. 如果一个对象的状态发生改变,依赖他的对象都将发生变化, 那么这种情况就适合使用观察者模式. 它包含两个术语,主题(Subject),观察者(O ...
- 【设计模式】观察者模式 Observer Pattern
定义:观察者模式定义了对象之间的一对多依赖.当“主题”(Object)状态改变事,所有依赖它的“观察者”(Observer)都会受到通知并自动更新.主题支持观察者订阅和退订. 观察者模式提供了一种对象 ...
- 【UE4 设计模式】观察者模式 Observer Pattern
概述 描述 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新.观察者模式又叫做 发布-订阅(Publish/Subscribe)模式 模型-视图(M ...
- 设计模式-观察者模式(Observer Pattern)
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
随机推荐
- cocos2d-x3.0-结合TH脚本引擎
近期自己在研究手机游戏开发,呵呵.引擎就选择了cocos2d-x,略微看了下感觉好像非常不错的样子. 写个一般的游戏,全然能够了.工作量也不会非常大,相对来说开发非常轻松了. 在脚本引擎的选择其中,当 ...
- Android如何创建背景透明的Dialog
一:控制Dialog 的背景方法:1.定义一个无背景主题主题<!--去掉背景Dialog--> <style name="NobackDialog" parent ...
- float:left 与display:inline的具体区别?
设了float:left的元素允许它的右边存在任何元素同行显示,不论是内联元素还是块元素.但它的左边还是不允许存在任何元素与之同行显示,哪怕其它的元素的代码在前,除非也给前面的元素加上float:le ...
- Android(java)学习笔记213:开源框架post和get方式提交数据(qq登录案例)
1.前面提到Http的get/post方式 . HttpClient方式,实际工作的时候不常用到,因为这些方式编写代码是很麻烦的 2.Android应用会经常使用http协议进行传输,网上会有很完善 ...
- 函数返回一个SqlDataReader对象
解决方法: 1.尝试使用dataset 2.执行数据库操作命令 SqlDataReader reader=mySqlCommand.ExecuteReader(CommandBehavior.Clos ...
- Array,ArrayList 和 List<T>的选择和性能比较.
Array Class Provides methods for creating, manipulating, searching, and sorting arrays, thereby serv ...
- windows 20003 扩展安装后不成功的原因
windows扩展如果安装不成功(PHP扩展)很大的可能就是那个DLL的权限不够.需要分配:AdministratorAuthenticater UsersIIS_WPGSYSTEMUsers
- Android布局管理器(表格布局)
表格布局有TableLayout所代表,TableLayout继承了LinearLayout,因此他的本质依然是LinearLayout. 表格布局采用行.列的形式来进行管理,在使用的时候不需要声明多 ...
- 开发自己的cordova插件
如果还没有配置过cordova环境,首先要下载nodejs,(下载地址https://nodejs.org/)下载完毕安装. 控制台: 1.输入npm -v 确定是否装上了 2.输入sudo npm ...
- Spring MVC中 controller方法返回值
1.返回ModelAndView 定义ModelAndView对象并返回,对象中可添加model数据.指定view 2.返回String 1.表示返回逻辑视图名 model对象通过 model.add ...