观察者模式(Head First设计模式学习2)
1.1观察者模式定义
在给出观察者模式的定义之前,我们先来看个报纸和杂志的订阅是怎么回事:
1.报社的业务就是出版报纸
2.向某家报社订阅报纸,只有新报纸出版,报社才会送给你,只要你是用户,他就会一直向你发送。
3.当你不向看报纸了,取消订阅,他们就不会发送报纸。
4.只要报社还在运营,就会有人订阅报纸或取消报纸订阅
其实这个过程就和我们的观察者模式的过程相似。所以我们可以简单的将观察者模式定义为:
出版社+订阅者=观察者模式
这个毕竟是简单的,下面我们给出正式的定义:
观察者模式定义了对象之间的一对多依赖,当一个被依赖者改变状态时,他所有的依赖者都会收到通知并自动更新。
通过出版社和正式定义应该很容易理解观察者模式了。需要注意的是观察者模式定义了一些列对象之间的一对多的关系,当被依赖者改变状态时,其他的依赖者都会收到通知。
下面通过例子来看看观察者是怎么实现一对多依赖,以及如何通知多个依赖对象的。
1.2一个观察者模式的例子
这里我们使用head first设计模式的例子,某公司成功中标了气象站的项目。下面给出该项目的大致需求:
1、气象站会不定时的对天气状况(温度、湿度、气压)进行统计,并且封装在气象站提供的WeatherData对象中。
2、希望某公司能及时的提供目前的状况、气象统计、简单的预报,三种信息必须及时更新。
3、气象站还希望能该公司能提供一组API,好让其他公司能够根据三种信息的更新来做出其他的反应。
以上对应的需求说明图如下。
气象站给出了WeatherData对象部分代码提示,剩余的需要该公司去完善:
public double Temperture ;
public double Humidity ;
public double Pressure ;
public void MeasurementsChanged();//当温度湿度气压改变时作出的反应
public void OnChaged();//激发温度,湿度,气压反应的方法
1.2.1使用策略中的原则
我们利用策略模式中提到的原则,来完成该部分任务。先抽象出变化部分,进行封装(原则一),在此,显示器的种类会经常变化,并且其需要显示不同的状态,我们可以在此使用一个接口(IDisplay),用来显示,所以可以在里面定义个Display方法。
接着分析,如果气象站有温度,气压,湿度变化时,要去通知订阅的对象。这些对象可以是一个都是显示器,为了能在被依赖对象里实现统一的动作——更新,我们除了需要维护一个订阅者列表(原则三使用组合),还需要让依赖实现统一的接口(IOberver),其里面的方法为Update。(原则二面向接口编程)在update方法中调用Display。
Note:其实上面的Display和Update方法可以在一个接口中实现,这里为了保持清晰,就单独去实现各个方法。为了保持和书上的内容接近以及大家的常用命名,上面的统一接口我让他的名字定义成了IObserver,下面的被依赖对象接口我会把他定义为ISubject,分别对应观察者,主题。
1.2.2维护观察者模式列表
在被依赖对象的接口中,肯定会包括RegisterObserver(IObserver o),RemoveObserver(IObserver o),NotifyObserver(),在每一个显示器中有个ISubject对象,以便在构造时或者使用其他方法,将显示器添加到订阅列表。这样就不用在ISubject中去添加,直接调用ISubject对象的RegisterObserver(IObserver o),就可以添加了。
这样设计的一个好处时,实现了ISubject和IObserver之间的松耦合,在向订阅列表中添加订阅者时,不需要更改ISubject中的任何代码,只要主题和观察者都实现了自己对象的接口,各自更改自己的方法,相互不影响。除了上述好处外,无论是主题还是观察者,都各自可以不用依赖于对方存在于其他非观察者模式的场合。这些也是设计模式中常用的一个原则:
原则四:为交互对象之间的松耦合设计而努力。
有了松耦合,我们就可以更好的应对软件设计中的变化。让软件很有弹性。
下面给出其对应的UML:
可以看到subject和observer是通过依赖于抽象来解耦的,WeatherData依赖于多个IObserver,显示器依赖于ISubject(显示器的依赖我只表达出了一个)。具体的代码实现,我会在最后一并给出。
1.3观察者模式UML图
1.4源码
源代码中ObserverPatternUMLLib项目主要是关于WeatherData和显示器的设计。
1.5关于推和拉以及观察者模式与委托的联系
关于观察者模式中推和拉以及C#语言里面提供的委托事件可以参考下面两篇文章
http://kb.cnblogs.com/page/49989/
http://www.cnblogs.com/JimmyZhang/archive/2008/06/18/1225061.html
1.6小结
本文主要给出了观察者模式的定义,通过一个实例来熟悉观察者模式的松耦合思想。重点在于如何实现主题和观察者的一对多关系松耦合,以及如何实现观察者对主题的依赖。
观察者模式(Head First设计模式学习2)的更多相关文章
- Java设计模式学习记录-观察者模式
前言 观察者模式也是对象行为模式的一种,又叫做发表-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式. 咱们目前用的最多的就是各种MQ(Message Queue ...
- 设计模式学习-使用go实现观察者模式
观察者模式 定义 适用场景 优点 缺点 代码实现 不同场景的实现方式 观察模式和发布订阅模式 参考 观察者模式 定义 观察者模式(Observer Design Pattern)定义了一种一对多的依赖 ...
- Java-马士兵设计模式学习笔记-总结
<马士兵设计模式学习>学习了以下模式: 1.装饰者模式(例子:水管工,木工) 2.策略模式(例子:老师用职称比大小.学生用成绩比大小) 3.简单工厂模式(例子:VechileFactory ...
- Java设计模式学习资源汇总
本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...
- python之路,Day24 常用设计模式学习
python之路,Day24 常用设计模式学习 本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...
- 设计模式学习--复合模式(Compound Pattern)
设计模式学习--复合模式(Compound Pattern) 概述 ——————————————————————————————————————————————————— 2013年8月4日<H ...
- Java设计模式学习总结
设计模式基础学习总结 这篇总结主要是基于我之前设计模式基础系列文章而形成的的.主要是把重要的知识点用自己的话说了一遍,可能会有一些错误,还望见谅和指点.谢谢 更多详细内容可以查看我的专栏文章:设计模式 ...
- Java设计模式学习记录-GoF设计模式概述
前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...
- C#大话设计模式学习总结
如有雷同,不胜荣欣,如转载,请注明 C#大话设计模式学习总结 一.工厂模式 面向对象的三个特性:封装,继承和多态 1.封装 Class Operate { privatedouble _numberA ...
- 7 种 Javascript 常用设计模式学习笔记
7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...
随机推荐
- linux shutdown命令
shutdown [-t 秒] [-arkhncfF] 时间 [警告信息] 常用选项与参数: -t sec : -t 后面加秒数,亦即『过几秒后关机』的意思 -k : 不要真的关机,只是发送警告信息出 ...
- Xshell和Xftp5配置连接阿里云服务器
配置Xftp5 配置成功后 配置Xshell 记住用户名和密码 连接成功
- MySQL-关于事务的使用
如果你一次执行单条查询语句, 则没有必要启用事务支持, 数据库默认支持SQL执行期间的读一致性, 如果你一次执行多条查询语句, 例如统计查询, 报表查询, 在这种场景下, 多条查询SQL必须保证整体的 ...
- NYOJ-------笨蛋难题四
笨蛋难题四 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 这些日子笨蛋一直研究股票,经过调研,终于发现xxx公司股票规律,更可喜的是 笨蛋推算出这 ...
- 【LeetCode】71. Simplify Path
Simplify Path Given an absolute path for a file (Unix-style), simplify it. For example,path = " ...
- python练习笔记——计算1/1-1/3+1/5-1/7……的和
1 / 1 - 1 / 3 + 1 / 5 - 1 / 7 + ....求100000个这样的分式计算之为是多少?将此值乘以4后打印出来,看看是什么? num_list = [] count = -1 ...
- pylot 学习笔记-使用
Console and Blocking Mode - Command Line Options: usage: run.py [options] args -a, --agents=NUM_AGEN ...
- Spring注解运行时抛出null
关于Spring的注解其实不难,大致需要以下几个流程: 一.配置Spring的注解支持 <?xml version="1.0" encoding="UTF-8&qu ...
- 批处理学习笔记6 - 重定向符>和>>
重定向符大概有6,7种,和%符号差不多各有各的用途.这里学习>和>> > 是左边的值把右边的值覆盖 >> 是左边的值添加在右边的值上面 rem 是批处理的注释,类 ...
- [svc]samba服务搭建
说实话搞这些很蛋疼, 没啥技术含量. What is Samba? 这个历史悠久了 Since 1992, Samba has provided secure, stable and fast fil ...