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

假如有这么一个项目,监控每天的天气状况WeatherData(温度,湿度,气压)。有布告板显示天气的不同内容。天气要实时更新,布告板内容也会随着更新。要求可扩展,将来还有可能有别的布告板,WeatherData还有可能添加新内容。

这么一个需要,我们的第一想法就是WeatherData中有三个属性,对应三个获取方法,有几个布告板那就写几个更新方法,在一个大更新方法中分别调用每个布告板的更新方法。

如果这么一写,如果未来又增加了新的布告板,那么就需要在现有的方法中增加这个新的布告板的更新方法,这么一修改了已经写好的代码,那么之前的测试就需要在重新测试一遍。而且这个更新的方法会越来越大,越来越头疼。而且如果有哪个布告板在运行的过程中不想要了,这没法办到。

看一下观察者模式解决这个问题。

直接看代码:

interface Observer {
public void update(float temp, float humidity, float preasure);
} interface DisplayElement {
public void display();
} class CurrentConditionsDisplay implements Observer, DisplayElement {
float temperature;
float humidity;
Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
} @Override
public void display() {
System.out.println("temperature, humidity, pressure is " + temperature + " " + humidity);
} @Override
public void update(float temp, float humidity, float preasure) {
this.temperature = temp;
this.humidity = humidity;
this.temperature = preasure;
}
} interface Subject {
public void registerObserver(Observer observer); public void removeObserver(Observer observer); public void notifyObserver();
} class WeatherData implements Subject {
ArrayList<Observer> observers;
float temperature;
float humidity;
float pressure; public WeatherData() {
this.observers = new ArrayList<>();
} @Override
public void registerObserver(Observer observer) {
this.observers.add(observer);
} @Override
public void removeObserver(Observer observer) {
int i = this.observers.indexOf(observer);
if (i > ) {
this.observers.remove(i);
}
} @Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
} public void measurementsChanged() {
notifyObserver();
} public void setMeasurements(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
} public class Test {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay display = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(, , );
display.display();
}
}

这里存在的一个问题是三个属性最好封装成一个对象,这样在以后新增其他属性时候方便修改。

一对多的关系:利用观察者模式,主题是一个有状态的对象,并且可以修改这些状态。另一方面,观察者也有一自己的状态,但是观察者的状态使用主题的状态来更新或显示。这样主题与观察者就能有一个一对多的关系。这里,主题是真正拥有对象的人,观察者只是主题的依赖者。

观察者模式提供了一种对象设计,让主题和观察者之间松耦合:
关于观察者的一切,主题只知道观察者实现了某个接口(Observer接口),主题并不需要知道观察者的具体类是谁和其他的细节。想要增加观察者,只需要实现这个接口。运行时,随时增加删除,主题并不会受到影响。我们可以独立的复用主题或者观察者的代码(在类里实现这些接口即可),改变主题或观察者的一方并不会影响到另一方,因为二者并非紧耦合。

Head First 设计模式--2 观察者模式 解耦的更多相关文章

  1. 实践GoF的23种设计模式:观察者模式

    摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...

  2. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  3. 设计模式之观察者模式(Observable与Observer)

    设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...

  4. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  5. php 设计模式之观察者模式(订阅者模式)

    php 设计模式之观察者模式 实例 没用设计模式的代码,这样的代码要是把最上面那部分也要符合要求加进来,就要修改代码,不符合宁增不改的原则 介绍 观察者模式定义对象的一对多依赖,这样一来,当一个对象改 ...

  6. [JS设计模式]:观察者模式(即发布-订阅者模式)(4)

    简介 观察者模式又叫发布---订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 举一个现实生活中的例子,例如小 ...

  7. 再起航,我的学习笔记之JavaScript设计模式18(观察者模式)

    观察者模式 观察者模式(Observer): 又被称为发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合. 创建一个观察者对象 首先我们创建一个闭包对象,让其在页面加 ...

  8. Head First设计模式之观察者模式

    一.定义 观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多 ...

  9. 设计模式之观察者模式(c++)

    Observer 模式应该可以说是应用最多.影响最广的模式之一,因为 Observer 的一个实例 Model/View/Control( MVC) 结构在系统开发架构设计中有着很重要的地位和意义, ...

随机推荐

  1. C#编程之委托与事件四(二)【转】

    C#编程之委托与事件(二)       我在上一篇文章(C#编程之委托与事件(一) )中通过示例结合的方法介绍了委托,在本文中,我同样以代码示例的方式来介绍C#里的事件机制. 二.事件   1.了解概 ...

  2. python 多线程就这么简单(续)

    之前讲了多线程的一篇博客,感觉讲的意犹未尽,其实,多线程非常有意思.因为我们在使用电脑的过程中无时无刻都在多进程和多线程.我们可以接着之前的例子继续讲.请先看我的上一篇博客. python 多线程就这 ...

  3. LightOj 1236 - Pairs Forming LCM (分解素因子,LCM )

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1236 题意:给你一个数n,求有多少对(i,  j)满足 LCM(i, j) = n, ...

  4. Assets和Raw区别

    在建立项目中一般会默认建立assets文件,当然我们还可以在res文件下面建立raw文件夹,这里面都可以存放一些多媒体文件或者文本信息,可以供我们在程序中使用. assets下面的文件不会被编译,通过 ...

  5. require,include,require_once,include_once的区别

    最近面试时被问到,一时间还真没想到太多,仅仅回答了大概的几个,于是回来再确认一下. 以下内容为网络摘抄: ①作用及用法  可以减少代码的重复 include(_once)("文件的路径&qu ...

  6. lua 环境揭秘

    什么是环境? http://www.lua.org/manual/5.1/manual.html#2.9 Besides metatables, objects of types thread, fu ...

  7. PAT——乙级真题1002代码

  8. .Net 中HashTable,HashMap 和 Dictionary<key,value> 和List<T>和DataTable的比较

    参考资料 http://www.cnblogs.com/MichaelYin/archive/2011/02/14/1954724.html http://zhidao.baidu.com/link? ...

  9. AJAX-----16HTML5实现大文件切割上传

    2点多接了个电话导致失眠,没办法,跑起来接着板砖了...... 废话不多说,直接走码... <!DOCTYPE html> <html lang="en"> ...

  10. Create Your Tab and LayerTabMenu In Katana

    感谢 http://tool.lu/pyc/ 这个牛逼的网站能反编译pyc...他妈的Katana太他妈无耻了,竟然不让自定义加Node Tab Content....只能反编译他的东西了... 研究 ...