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)的更多相关文章

  1. Java设计模式学习记录-观察者模式

    前言 观察者模式也是对象行为模式的一种,又叫做发表-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式. 咱们目前用的最多的就是各种MQ(Message Queue ...

  2. 设计模式学习-使用go实现观察者模式

    观察者模式 定义 适用场景 优点 缺点 代码实现 不同场景的实现方式 观察模式和发布订阅模式 参考 观察者模式 定义 观察者模式(Observer Design Pattern)定义了一种一对多的依赖 ...

  3. Java-马士兵设计模式学习笔记-总结

    <马士兵设计模式学习>学习了以下模式: 1.装饰者模式(例子:水管工,木工) 2.策略模式(例子:老师用职称比大小.学生用成绩比大小) 3.简单工厂模式(例子:VechileFactory ...

  4. Java设计模式学习资源汇总

    本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...

  5. python之路,Day24 常用设计模式学习

    python之路,Day24 常用设计模式学习   本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...

  6. 设计模式学习--复合模式(Compound Pattern)

    设计模式学习--复合模式(Compound Pattern) 概述 ——————————————————————————————————————————————————— 2013年8月4日<H ...

  7. Java设计模式学习总结

    设计模式基础学习总结 这篇总结主要是基于我之前设计模式基础系列文章而形成的的.主要是把重要的知识点用自己的话说了一遍,可能会有一些错误,还望见谅和指点.谢谢 更多详细内容可以查看我的专栏文章:设计模式 ...

  8. Java设计模式学习记录-GoF设计模式概述

    前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...

  9. C#大话设计模式学习总结

    如有雷同,不胜荣欣,如转载,请注明 C#大话设计模式学习总结 一.工厂模式 面向对象的三个特性:封装,继承和多态 1.封装 Class Operate { privatedouble _numberA ...

  10. 7 种 Javascript 常用设计模式学习笔记

    7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...

随机推荐

  1. tracteroute路由追踪

    traceroute 跟踪数据包到达网络主机所经过的路由工具: 是用来发出数据包的主机到目标主机之间所经过的网关的工具.traceroute 的原理是试图以最小的TTL发出探测包来跟踪数据包到达目标主 ...

  2. 转载:【微信小程序】 wx:if 与 hidden(隐藏元素)区别

    条件渲染 顾名思义所谓的条件渲染,就是通过条件来判断是否需要渲染该代码块.条件渲染主要是用到wx:if 和 block wx:if 这两个,第一个相信好理解,第二个是在block里面进行条件渲染,这里 ...

  3. 架构-LAMP特级学习(网站服务器监控)

    1.服务监控(SNMP配合CACTI监控) Apache Web服务监控 MySQL数据库监控 磁盘空间监控 2.流量监控(SNMP配合MRTG监控) 网站流量监控 3.使用SNMP可以获取被监控服务 ...

  4. SVN访问版本库精细的权限控制

    SVN精细权限控制本章将详细介绍前一章所涉及的两个配置文件, svnserve.conf 和 authz.conf,通过对配置逐行的描述,来阐明其中的一些细节含义.除此之外的其他配置.安装等内容,不是 ...

  5. swift上传图片

    import UIKit import AFNetworking class YJRequest: NSObject { //#pragma mark - 上传图片 func uploadImageW ...

  6. windows系统定时重启自定义exe程序

    工作需要, Windows系统定时重启自定义exe程序. 写了如下程序, 按照说明(readme.txt)修改批处理文件中的四个参数即可: 1.readme.txt 第一个参数:进程名(不用带exe) ...

  7. <转>字符编码笔记:ASCII,Unicode和UTF-8

    本文转自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 今天中午,我突然想搞清楚Unicode和UTF-8之间 ...

  8. 【LeetCode】166. Fraction to Recurring Decimal

    Fraction to Recurring Decimal Given two integers representing the numerator and denominator of a fra ...

  9. 分布式缓存技术memcached学习系列(五)—— memcached java客户端的使用

    Memcached的客户端简介 我们已经知道,memcached是一套分布式的缓存系统,memcached的服务端只是缓存数据的地方,并不能实现分布式,而memcached的客户端才是实现分布式的地方 ...

  10. Java实现文件自动打包成zip并下载的代码

      import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java. ...