上次总结完了策略模式,这次继续跟随着《Head First 设计模式》,聊下观察者模式。

现在你接到了一个气象监测应用的项目,此系统中的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(获取来自气象站的数据,并更新布告板)和布告板(显示装置这只是其中一个,还有气象统计和天气预报布告板显示目前天气状况给用户看)。大概是下面这样的图:(右边的显示装置只是其中一个布告板,目前还有气象统计和天气预报)

WeatherData的源代码主要结构如下:

WeatherData可以通过三个get方法获取到实际的天气数据。 一旦气象测量数据有更新,WeatherData的measurementsChanged()方法就会被调用。而一旦数据更新WeatherData就要立刻通知三个布告板。

现在我们的任务是实现measurementsChanged(),让它更好的更新三个布告板显示的数据。要求是此系统必须有可扩展性,让其他人员简历定制的布告板,用户可以随心所欲添加删除布告板。而目前只有三个布告板。

一个错误示范:

里面的update方法类似于将新的temp,humidity,pressure赋值给三个布告板的成员变量。

为什么说是错误的呢?

1.它针对实现编程,没有针对接口,这样导致每次增加布告板都要修改里面的代码。

2.可能改变的地方没有封装起来(三个更新方法直接在measurementsChanged()中)。

3.这样根本不可能在运行时动态添加删除一些布告板。

所以它的可扩展性非常差。

对此,可以用观察者模式。那什么是观察者模式呢?

观察者模式可以用订阅报纸来诠释。

1报社的业务就是出版报纸。
    2向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸。
当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。
    3当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。
    4只要报社还在运营,就会一直有人(或单位)向他们订阅报纸或取消订阅报纸。
向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸。

此时,出版社可以看做是观察者模式的主题,订阅者是观察者。可以用一张图的来解释:

如图,老鼠、狗、猫对象已经订阅主题,所以主题有更新立刻通知它们,而鸭子没有订阅,主题的变化它什么也不知道。鸭子哪天想知道主题更新状态可以自己订阅主题,老鼠、狗、猫对象哪天不想知道主题动态了也可以取消订阅,一切自愿原则,而且主题和动物对象们互相不影响。、

来个官方的定义:

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

以下是最常用的实现观察者模式的示意图:

观察者模式强调的是松耦合的原则:当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加观察者。事实上,在运行时我们可以用新的观察者取代现有的观察者,主题不会受到任何影响。同样的,也可以在任何时候删除某些观察者。有新类型的观察者出现时,主题的代码不需要修改。假如我们有个新的具体类需要当观察者,我们不需要为了兼容新类型而修改主题的代码,所有要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。主题不在乎别的,它只会发送通知给所有实现了观察者接口的对象。

松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

根据以上叙述,可以将之前的任务设计如下图:

实现气象站项目的代码:

首先是接口:

WeatherData的代码:

通过多态,只需要实现同一个接口的类都可注册,所以可以用一个集合来注册和取消观察。当数据发生改变,就遍历集合的所有元素,调用元素的update方法。

布告板代码:

这样在运行中,我们可以new出一个布告板对象(比如CurrentConditionsDisplay),将一个WeatherData对象作为参数传入,这样在构造上方法中就立刻将CurrentConditionsDisplay对象注册到这个WeatherData对象中。

测试程序可以这样写:

调侃《HeadFirst设计模式》之观察者模式相关推荐

  1. HeadFirst设计模式之观察者模式学习

    一.观察者模式的定义: 观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者,都会收到通知并自动更新. 二.我个人对于观察者模式的理解: 当主题发生改变时,自动通知到所有观察者, ...

  2. headfirst设计模式(2)—观察者模式

    定义 观察者模式(有时又被称为发布(publish)-订阅(Subscribe)模式,在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察 ...

  3. 【HeadFirst设计模式——开篇】

    近期在看HeadFirst,接下来的一段时间会陆续更新有关HeadFirst设计模式相关的文章.记得非常久之前在学习大话设计模式的时候,仅仅是走马观花的大致走过一遍.至于里面非常多东西都掌握的不是非常 ...

  4. HeadFirst设计模式(模式总览速查)

    本文用于记录本人阅读完HeadFirst设计模式一书后对此书的总结,总结系个人理解并简化提炼,方便使用设计模式时速查,如有错漏,请积极指出,本人将虚心接受并及时改正. 1. 策略模式 1.1 使用前提 ...

  5. 设计模式:观察者模式--Observer

    一.什么是观察者模式 1.生活中的观察者模式 1.警察抓小偷 在现实生活中,警察抓小偷是一个典型的观察者模式「这以一个惯犯在街道逛街然后被抓为例子」,这里小偷就是被观察者,各个干警就是观察者,干警时时 ...

  6. Headfirst设计模式的C++实现——策略模式(Strategy)

    前言 最近在学习<Headfirst设计模式>,里面的例子都是Java的.但是我对Java并不熟悉,所以试着用C++来实现书中的例子. 先来看看Duck以及子类 Duck.h 1 #inc ...

  7. Delphi 设计模式:《HeadFirst设计模式》Delphi代码---模式小结之一个叫声接口和几只鸭子[转]...

    一.一个叫声接口和几只鸭子 从一个叫声接口开始. {<HeadFirst设计模式>Delphi代码之模式小结 } { 一个叫声接口                            } ...

  8. java 观察者模式_图解Java设计模式之观察者模式

    图解Java设计模式之观察者模式 天气预报项目需求 天气预报设计方案 1 - 普通方案 观察者模式(Observer)原理 观察者模式解决天气预报需求 观察者模式在JDK应用的源码分析 天气预报项目需 ...

  9. 游戏服务器架构-设计模式之观察者模式和发布订阅模式真的一样吗?

    前面我给大家分享了观察者模式和发布订阅模式,有人私信给我说这俩不是一样嘛,大体没什么区别,我猜测大多数认为这两者是一样的可以继续阅读这两篇文章,如果还不能解答你的问题,我相信这篇文章对比两者的关系会让 ...

  10. Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---模板方法模式之CoffeineBeverageWithHook[转]...

    模板方法模式定义了一个算法骨架,允许子类对算法的某个或某些步骤进行重写(override).   1   2{<HeadFirst设计模式>之模板方法模式 }   3{ 编译工具: Del ...

最新文章

  1. 计算机公开课课前互动小游戏,公开课前课堂小游戏
  2. 惠普计算机电源怎么设置充电,惠普电脑怎么用外接电源时不用电池怎样设置的...
  3. 小说里的lt什么意思_脂肪醇里的脂肪是什么意思
  4. vc6.0 简易的tcp网络讲解(二)
  5. python django -5 进阶
  6. 论文浅尝 | 近期论文精选
  7. MongoDB 谨防索引seek的效率问题【华为云技术分享】
  8. 解决文件上传_使用FastDfs上传头像上传不成功的问题---SpringCloud Alibaba_若依微服务框架改造---工作笔记002
  9. C# 图片处理之:旋转图片任意角度
  10. HTML5div css入门案例,div+css教学教案(学习入门到精通~)详细讲解.doc
  11. freemarker生成java代码,freeMarker之根据模板生成JAVA代码示例
  12. doc转docx文件会乱吗_我电脑里所有Word的doc格式都变成了docx格式.传Word文件给别人都打不开.请问为什么?...
  13. 信号与线性系统分析(吴大正,郭宝龙)(2-冲激函数)
  14. python微信语音转发方法_最简单的微信语音转发方法,保证看一遍就会
  15. android远程桌面工具下载,Android远程桌面助手
  16. 关于flash跨域问题
  17. 10个深度学习软件_关于深度学习的10个问题
  18. 解决vscode打开txt文件乱码
  19. linux 查找mysql rpm包位置_linux如何查看rpm包的安装路径办法
  20. Windows内核原理与实现之Windows设备驱动程序

热门文章

  1. 研发团队如何应对源源不断的、来自多方的用户需求和期待?(一)
  2. Google Photos上线一年 照片存储达13.7PB
  3. 灵魂代码及改造魂魄翻译
  4. IntelliJ IDEA 开发工具破解
  5. 5G已经开始布局,云电脑时代即将到来!
  6. 计算机的数学发展史论文,数学史毕业论文
  7. CAD 二次开发--多段线绘制
  8. Python frozenset集合(set集合的不可变版本)
  9. 固高数控工作台的刀补插补程序开发(逐点比较法,数字积分法)
  10. 关于docker的docker-entrypoint.sh脚本运行机制