zoukankan      html  css  js  c++  java
  • 观察者模式(Head First设计模式学习2)

    1.1观察者模式定义

    在给出观察者模式的定义之前,我们先来看个报纸和杂志的订阅是怎么回事:

    1.报社的业务就是出版报纸

    2.向某家报社订阅报纸,只有新报纸出版,报社才会送给你,只要你是用户,他就会一直向你发送。

    3.当你不向看报纸了,取消订阅,他们就不会发送报纸。

    4.只要报社还在运营,就会有人订阅报纸或取消报纸订阅

    其实这个过程就和我们的观察者模式的过程相似。所以我们可以简单的将观察者模式定义为:

    出版社+订阅者=观察者模式

    这个毕竟是简单的,下面我们给出正式的定义:

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

    通过出版社和正式定义应该很容易理解观察者模式了。需要注意的是观察者模式定义了一些列对象之间的一对多的关系,当被依赖者改变状态时,其他的依赖者都会收到通知。

    下面通过例子来看看观察者是怎么实现一对多依赖,以及如何通知多个依赖对象的。

    1.2一个观察者模式的例子

    这里我们使用head first设计模式的例子,某公司成功中标了气象站的项目。下面给出该项目的大致需求:

    1、气象站会不定时的对天气状况(温度、湿度、气压)进行统计,并且封装在气象站提供的WeatherData对象中。

    2、希望某公司能及时的提供目前的状况、气象统计、简单的预报,三种信息必须及时更新。

    3、气象站还希望能该公司能提供一组API,好让其他公司能够根据三种信息的更新来做出其他的反应。

    以上对应的需求说明图如下。

    image

    气象站给出了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:

    image

    可以看到subject和observer是通过依赖于抽象来解耦的,WeatherData依赖于多个IObserver,显示器依赖于ISubject(显示器的依赖我只表达出了一个)。具体的代码实现,我会在最后一并给出。

    1.3观察者模式UML图

    image

    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小结

    本文主要给出了观察者模式的定义,通过一个实例来熟悉观察者模式的松耦合思想。重点在于如何实现主题和观察者的一对多关系松耦合,以及如何实现观察者对主题的依赖。

  • 相关阅读:
    gitlab
    MySQL千万级别大表,你要如何优化?
    kafka入门
    zookeeper的原理和应用
    MySQL 性能优化之慢查询
    Redis一些新的看法
    mysql 数据库锁
    MYSQL查看进程和kill进程
    hadoop批量命令脚本xcall.sh及jps找不到命令解决
    java stream 处理分组后取每组最大
  • 原文地址:https://www.cnblogs.com/lzhp/p/3353647.html
Copyright © 2011-2022 走看看