`
810364804
  • 浏览: 785173 次
文章分类
社区版块
存档分类
最新评论

学习笔记 ---- 设计模式之观察者模式

 
阅读更多
转载:http://www.cnblogs.com/shitouer/archive/2011/09/02/2164048.html

Head First里边给出的场景是

客户需要这样一个App:一个WheatherData类可以从气象站获得气象信息(temperature, humidity, pressure and so on).一旦这些信息改变,就会更新气象站的三个公告板(CurrentConditionBulletin, StatisticsBulletin and ForecastBulletin, 另外,用户还可以随时增加/删除/更改自己的布告板)。

客户给出了WheatherData的类图:

结合以上描述和类图我们已知:

1. 由Getter可以或得气象信息

2. 一旦气象信息有改变,调用measurementsChanged()方法更新所有的布告板

3. 现在需要三个布告板

4. Customer可以定义自己的布告板

首先看一个不好的实现:

publicclass WeatherData {       
 
        publicvoid MeasurementsChanged()
        {
            floattemp = getTemperature(); 
            floathumidity = getHumidity(); 
            floatpressure = getPressure();
            currentConditionsDisplay.update(temp, humidity, pressure); 
            statisticsDisplay.update(temp, humidity, pressure);
            forecastDisplay.update(temp, humidity, pressure);
        }
}
?

  为什么不好呢?可以从已经知道的几个设计原则入手:

1. 找出程序中变化的部分,将其与固定不变的部分隔离

在这个场景中,变化的是布告栏的类型和数量,在这个不好的例子中,我们改变布告栏的类型和数量,势必要修改WheatherData这个类。如何才能可以随意修改布告栏的数量和类型,却不用修改WheatherData类呢?

2. 针对接口编程,不针对实现编程

明显,statisticsDisplay,statisticsDisplay,forecastDisplay均是具体的实现的编程,如果以后我们增加修改布告栏,都必须修改这段程序。而且三个方法( update() )的名字和参数相同,一个统一的接口可行?

可以根据报纸订阅业务对观察者模式有一个简单的了解:

观察者模式类图:

Subject

主题接口,也即可观察者(Observable),对象使用此接口注册为观察者,或者把自己从观察着中删除。每个主题可以有多个观察者。

ConcreteSubject

一个具体主题实现了主题接口,除了注册和撤销之外,具体主题还实现了notifyObservers()方法,这个方法用来在主题状态改变时更行所有的观察者。具体主题也可能有设置和获取状态的方法。

Observer

所有潜在的观察者必须实现观察者接口,这个接口只有update()方法,当主题改变时,它被调用。

ConcreteObserver

具体的观察者可以是任何实现了Observer接口的类。观察者必须注册具体主题,一边接收更新。

基本原则:为了交互对象之间的松耦合设计而努力

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

观察者模式中,一对多的关系体现在哪里?

这个模式中,主题是具有状态的对象,并且可以控制这个状态,也就是说,是一个具有“状态”的主题。

另一方面,观察者使用这些状态,虽然这些状态并不属于他们。有多个观察者,依靠主题来告诉他们主题状态何时变了。

这就产生了一个关系,一个“主题”对多个“观察者”的关系

松耦合设计威力体现在哪里?

当两个对象松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者松耦合。

下面我们根据观察者模式来画出开篇WheatherStation的类图

代码如下

  ISubject:
?
importorg.jpatterns.gof.ObserverPattern;
 
@ObserverPattern(
        comment="ISubject: Interface of Observer Pattern"
)
publicinterface ISubject {
    voidregisterObserver(IObserver o);
    voiddeleteObserver(IObserver o);
    voidnotifyObservers();
}
  IObserver:
?
importorg.jpatterns.gof.ObserverPattern;
 
@ObserverPattern(
        comment="IObserver: Interface of Observer Pattern"
)
publicinterface IObserver {
    voidupdate(floattemp, floathumidity, floatpressure);
}
  实现了ISubject接口的WheatherData:
?
importjava.util.ArrayList;
 
importorg.jpatterns.gof.ObserverPattern;
 
@ObserverPattern(comment = "WheatherData: Concrete Subject of Observer Pattern")
publicclass WheatherData implementsISubject {
    privateArrayList<IObserver> observers;
    privatefloat temperature;
    privatefloat humidity;
    privatefloat pressure;
 
    publicWheatherData() {
        this.observers = newArrayList<IObserver>();
    }
 
    @Override
    publicvoid registerObserver(IObserver o) {
        observers.add(o);
    }
 
    @Override
    publicvoid deleteObserver(IObserver o) {
        if(observers.indexOf(o) >= 0) {
            observers.remove(o);
        }
    }
 
    @Override
    publicvoid notifyObservers() {
        for(inti = 0; i < observers.size(); i++) {
            IObserver observer = observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }
 
    publicvoid measurementsChanged() {
        this.notifyObservers();
    }
 
    publicvoid setMeasurements(floattemperature, floathumidity, floatpressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        this.measurementsChanged();
    }
}
  实现了IObserver接口的一个Bulletin:
?
publicclass CurrentConditionsBulletin implementsIObserver, IDisplayElement {
 
    privatefloat temperature;
    privatefloat humidity;
    privateISubject wheatherData;
 
    publicCurrentConditionsBulletin(ISubject wheatherData) {
        this.wheatherData = wheatherData;
        wheatherData.registerObserver(this);
    }
 
    @Override
    publicvoid update(floattemp, floathumidity, floatpressure) {
        this.temperature = temp;
        this.humidity = humidity;
        this.display();
    }
 
    @Override
    publicvoid display() {
        System.out.println("Current Conditions: " + this.temperature
                +"F Degrees and " + this.humidity + "% Humidity");
    }
}
  创建气象站,将程序run起来:
?
publicclass WheatherStation {
 
    publicstatic void main(String[] args) {
        WheatherData wheatherData = newWheatherData();
        IObserver o1 = newCurrentConditionsBulletin(wheatherData);
        IObserver o2 = newStatisticsBulletin(wheatherData);
        IObserver o3 = newForecastBulletin(wheatherData);
        IObserver o4 = newCustomBulletin(wheatherData);//自定义的
        wheatherData2.setMeasurements(20,20,20);
    }
 
}

  省略了好多注释啊,想好好理解,还是推荐去看HeadFirst吧,说实话,真本书真好!

其实在java中已经有内置的观察者模式。java.util中的Observable(类)和Observer(接口)。但是缺点不少,例如违反了:针对接口变成,而不是针对实现编程和多用组合少用继承两个原则,而且起nofify也依赖顺序。

观察者模式的要点:

观察者定义了对象之间一对多的关系。

主题用一个共同的接口来更新观察者。

观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口。

使用此模式,可以从可观察者推或者拉数据。

有多个观察者时,不可以依赖特定的通知次序。

要注意java.util.Observable实现上带来的问题。

如果有必要的话,可以实现自己的Observable。

观察者模式的应用

观察者模式的优点

观察者和可观察者之间是抽象耦合

建立了一套完整的触发链

观察者模式的缺点

多级触发的效率问题

Java中消息的通知默认是顺序执行的,一个观察者卡壳,会影响整体的效率

观察者模式的使用场景

可拆分的关联行为场景

事件多级触发的场景

跨系统的消息交换场景

分享到:
评论

相关推荐

    HeadFirst 设计模式学习笔记2--观察者模式 demo

    HeadFirst 设计模式学习笔记2--观察者模式 demo http://blog.csdn.net/laszloyu/archive/2010/05/12/5581769.aspx

    尚硅谷设计模式源码笔记课件.zip

    行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式) 2) 学习目标:通过学习,学员...

    PHP设计模式大全 学习笔记

    在PHP学习中,收集了一些常用的编程方法和思想,集中详细的记录了9种设计模式的设计思路和用法。比如:工厂模式,单例模式,注册模式,适配器模式,观察者模式等

    java-design-patterns:Java 设计模式学习笔记

    Java Design PatternsJava 设计模式学习笔记,简单易懂,每个模式都有相应的代码示列,帮助学习理解。在线阅读地址:设计原则创建型模式作用:将创建与使用代码解耦结构型模式作用:将不同的功能代码解耦桥接模式...

    设计模式笔记(包含所有设计模式)个人总结提炼笔记

    3. 行为型模式:行为型模式关注对象之间的通信和协作,包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。这些模式可以帮助...

    设计模式学习笔记

    2.1观察者模式(不依赖jdk) 博文链接:https://biaowen.iteye.com/blog/505950

    关于自己学习设计模式的笔记整理

    该文档是自己在学习设计模式时整理的常用设计模式pdf文档,包括源码,包括装饰模式,代理模式,责任链模式,命令模式,解释器模式,迭代器模式,备忘录模式,观察者模式,工厂模式,建造者模式,适配器模式,桥梁...

    java设计模式(收集整理,学习笔记)

    是我在学习设计模式时整理的,其中一些是我自己学习,很多来自网络.希望对模式有兴趣的朋友有帮助,我会很高兴.

    java-patterns:Java 23种基本的设计模式整料整理学习,责任链模式过滤器,工厂模式BeanFactory,观察者模式ContextListen等。结合Spring源码理解学习

    describe:设计模式学习笔记 逻辑结构图 代码结构图 设计模式简述 创建型模式,共五种:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 结构型模式,共七种:适配器模式,装饰器模式,代理模式,...

    asp.net知识库

    VS2005 ASP.NET本地化学习笔记&感受 在自定义Server Control中捆绑JS文件 Step by Step 深度解析Asp.Net2.0中的Callback机制 使用 Web 标准生成 ASP.NET 2.0 Web 站点 ASP.NET 2.0基于SQLSERVER 2005的aspnetdb.mdf...

    java-design-patterns:java 学习模式

    设计模式之UML 类图以及类间关系(泛化 、实现、依赖、关联、聚合、组合) 类图用于描述系统中所包含的类以及它们之间的相互关系,帮助人们简化对系统的理解,它是系统分析和设计阶段的重要产物,也是系统编码和测试...

    PHP常用的三种设计模式汇总

    本篇文章是学习PHP中常用的三种设计模式的笔记及总结,不管采用哪一门语言开发什么,几乎都会使用到设计模式,我们为什么需要设计模式呢?它的诞生对于我们开发人员来说有什么样的作用与意义呢? 相信做iOS开发的...

    左程云leetcode-hjLearningNotes:hj学习笔记

    第一部分:设计模式 & UML 简单工厂 工厂方法模式 抽象工厂模式 策略模式 责任链模式 命令模式 模板方法模式 适配器模式 代理模式 外观模式 组合模式 装饰模式 享元模式 桥接模式 Builder模式 状态模式 解释器模式 ...

    study-notes:个人学习笔记

    study-notes个人学习笔记目录JavaScriptCSSHTML碎片知识点lifecircleReact虚拟DOMJSXbuild-your-own-reactHTTPHttp 协议跨域HTTPSTCP/IP资源缓存js设计模式策略模式中介者模式单例模式观察者模式发布订阅模式数据...

    java8源码-akangaroo:学习笔记,完善中

    学习笔记较长,如果想查看文章的目录,chrome浏览器可以配合简悦插件使用,或者下载到本地使用Typora打开。 :hot_beverage: Java基础 Java容器 Java并发 数据结构和算法 数据结构 树 图 算法 分治 动态规划 回溯 ...

    design-patterns--node.js:该存储库可用于学习设计模式以及编写更好的Node.js代码。 它包含一些经典的GoF设计模式的集合,这些模式使用JavaScript和ES6类以及Node.js API在JavaScript中实现

    该存储库可用于学习设计模式以及编写更好的Node.js代码。 它包含一些经典的GoF设计模式的集合,这些模式使用JavaScript和ES6类以及Node.js API在JavaScript中实现。 感谢并非常欢迎您做出贡献,调整现有模式的...

    java8源码-jcohy-study-sample:个人学习整理

    java8 源码 本项目已迁移至 ...策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。大致分为四类关系: jcohy-study-

    hope::artist_palette: Java 学习笔记

    避坑笔记2021CICDCI/CD流程以及原理说明设计模式:策略模式单例模式工厂模式装饰器模式观察者模式适配器模式模板方法模式SpringBoot:SpringBoot(1):公共配置SpringBoot(2):generatorSpringBoot(3):docker部署...

    软件工程课堂笔记+期末试题

    能学到什么:①工厂模式、策略模式、观察者模式等都是怎么在Spring中体现的;②IOC、AOP、代理、切面、循环依赖都是如何设计和实现的。 阅读建议:此资源以开发简化版Spring学习其原理和内核,不仅是代码编写实现也更...

Global site tag (gtag.js) - Google Analytics