Head First 设计模式--2 观察者模式 解耦
观察者模式定义了对象之间一对多的依赖,这样依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
假如有这么一个项目,监控每天的天气状况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 观察者模式 解耦的更多相关文章
- 实践GoF的23种设计模式:观察者模式
摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 设计模式之观察者模式(Observable与Observer)
设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...
- 8.5 GOF设计模式四: 观察者模式Observer
GOF设计模式四: 观察者模式Observer 现实中遇到的问题 当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式 观察者模式 ...
- php 设计模式之观察者模式(订阅者模式)
php 设计模式之观察者模式 实例 没用设计模式的代码,这样的代码要是把最上面那部分也要符合要求加进来,就要修改代码,不符合宁增不改的原则 介绍 观察者模式定义对象的一对多依赖,这样一来,当一个对象改 ...
- [JS设计模式]:观察者模式(即发布-订阅者模式)(4)
简介 观察者模式又叫发布---订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 举一个现实生活中的例子,例如小 ...
- 再起航,我的学习笔记之JavaScript设计模式18(观察者模式)
观察者模式 观察者模式(Observer): 又被称为发布-订阅者模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合. 创建一个观察者对象 首先我们创建一个闭包对象,让其在页面加 ...
- Head First设计模式之观察者模式
一.定义 观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多 ...
- 设计模式之观察者模式(c++)
Observer 模式应该可以说是应用最多.影响最广的模式之一,因为 Observer 的一个实例 Model/View/Control( MVC) 结构在系统开发架构设计中有着很重要的地位和意义, ...
随机推荐
- Inside Flask - globals 全局变量(对象代理)
Inside Flask - globals 全局变量(对象代理) 框架是一个容器,在框架内编程,一般是要遵守框架的约定和使用模式.通常这样的模式是 IoC,即由框架调用用户的代码,而不是用户调用框架 ...
- nginx json 格式输出
log_format logstash_json '{ "@timestamp": "$time_local", ' ...
- html5 canvas围绕中心点旋转
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- HTML 中按钮作为form表单元素提交特性两则 --- 参HTML考标准分析
相同name的submit 类型的input提交行为 描述 这种情况, <input type="submit" name="ACTION" value= ...
- Linux系统编程--文件IO操作
Linux思想即,Linux系统下一切皆文件. 一.对文件操作的几个函数 1.打开文件open函数 int open(const char *path, int oflags); int open(c ...
- 安装eclipse的hadoop开发环境
eclipse:安装路径/usr/local/eclipse hadoop-2.5.2 /usr/local/hadoop/hadoop-2.5.2 hadoop2x-eclipse-plugin-m ...
- 高级Javascript调试——console.table()
原文:http://www.mariusschulz.com/2013/11/13/advanced-javascript-debugging-with-consoletable 本文只是简单翻译,部 ...
- 各大Oj平台介绍 刷题平台
https://leetcode.com/ http://www.cnblogs.com/lzmfywz/archive/2012/02/07/2342010.html 1.题库与网站资源题库-在线提 ...
- windows系统上安装与使用Android NDK r5 (转)
windows系统上安装与使用Android NDK r5 很早就听说了android的NDK应用,只是一直没有时间去研究,今天花了点时间在windows平台搭建了NDK环境,并成功运行了第一个简单 ...
- WITH AS的含义
一.WITH AS的含义WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候,是为了让S ...