[head first 设计模式]第二章 观察者模式

假如我们有一个开发需求——建造一个气象观测站展示系统。需求方给我们提供了一个WeatherObject对象,能够自动获得最新的测量数据。而我们要建立一个应用,有三种布告版,分别显示目前的状况,气象统计,简单预报。三种布告板能即时显示WeatherObject对象中更新的数据。

​同时,我们需要这是一个可扩展的气象站,可以公布一组api,好让其他开发人员写出自己的布告板插入此应用中。

​我们首先来看看我们的大致系统框架

我们的工作就算建立一个应用,利用weatherData对象取得数据,并更新布告板。

根据weatherData源文件,我们的工作是实现measurementChanged(),当测量数据备妥时,measurementChanged()方法将会被调用。

先来看一个可能的实现,

很明显,这个实现并不妥当。回想第一章的OO原则,会发现我们在针对具体实现编程,这会导致当有新需求时我们必须修改程序。同时,更新布告板的代码会经常改变,我们应该尽可能将其封装。

接下来我们将应用观察者模式来改进现有设计。

以报纸订阅为例,我们像某家报社订阅报纸,只要他们有新报纸初版,就会给派送给订户。而订户不想要了,就可以取消订阅。只要报社还在运营,就不断有人订阅或者取消订阅报纸。

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

如果了解了报纸订阅是怎么回事,观察者模式也大体如此。出版者即为观察者模式中的主题(Subject),订阅者即为观察者模式中的观察者(Observer)

定义观察者模式

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

类图如图所示

观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

对于观察者,主题只关心观察者实现了Observer接口,主题并不关心观察者的细节。

任何时候都可以新增观察者,因为主题唯一以来的东西是一个实现了Observer接口的对象列表,同时,也可以在任何时候删除观察者。

改变主题或观察者中的其中一方,并不会影响到另一方。

设计原则

设计应该尽可能降低交互对象之间的耦合度

依照观察者模式,得到我们的新设计

当前,我们暂时不用Java内置的观察者模式,而是自己实现这部分代码。

public interface Observer {
public void update(float temp,float humidity,float pressure);
}
public interface Subject {
public void notifyObserver();
public void removeObserver(Observer observer);
public void registerObserver(Observer observer); }
public interface DisplayElement {
public void display();
}
import java.util.ArrayList;
import java.util.List; public class WeatherData implements Subject {
private List<Observer> Observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData()
{
Observers = new ArrayList<Observer>();
} @Override
public void notifyObserver() {
for (Observer o:
Observers ) {
o.update(temperature,humidity,pressure);
}
} @Override
public void removeObserver(Observer observer) {
Observers.remove(observer);
} @Override
public void registerObserver(Observer observer) {
Observers.add(observer);
} public void measurementChanged()
{
notifyObserver();
} public void setMeasurements(float temperature,float humidity,float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementChanged();
}
}
public class CurrentConditionsDisplay implements Observer,DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
@Override
public void display() {
System.out.println("Current conditions: "+temperature+"F degrees and "+humidity+"% humidity");
} @Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
} public CurrentConditionsDisplay( Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
} }
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay =
new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80,65,30.4f);
}
}

使用Java内置的观察者模式

Java api有自带的观察者模式,包含Observer接口和Observable类,在使用上更加方便,很多功能已经事先准备好了。如下是我们使用Java内置观察者模式修改后的设计。

注册/删除观察者

调用Observable对象的addObserver方法和deleteObserver方法即可

被观察者送出通知

首先调用setChanged()方法,标记状态已经改变,后调用notifyObservers(),那么所有观察者都会调用自身的update方法。

import java.util.Observable;
import java.util.Observer; public class CurrentConditionsDisplay implements Observer,DisplayElement{
private double temperature;
private double humidity;
private Observable observable;
@Override
public void display() {
System.out.println("Current temperature "+temperature+"F degrees and "+humidity+"%humidity");
} public CurrentConditionsDisplay(Observable observable)
{
this.observable = observable;
observable.addObserver(this);
} @Override
public void update(Observable o, Object arg) {
if(o instanceof WheatherData)
{ temperature = ((WheatherData) o).getTemperature();
humidity = ((WheatherData) o).getHumidity();
display();
}
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Observable; public class WheatherData extends Observable {
private double temperature;
private double humidity;
private double pressure;
public double getHumidity() {
return humidity;
} public double getPressure() {
return pressure;
} public double getTemperature()
{
return temperature;
} public void setMeasurements(double temperature,double humidity,double pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
setChanged();
notifyObservers();
}
}

不幸的是,observable是一个类而不是接口,导致我们难以继承其他类,同时也无法拥有自己独特的实现。

在实际使用时,我们需要权衡是使用jdk自带的观察者模式亦或是由自己实现。

[head first 设计模式]第二章 观察者模式的更多相关文章

  1. 设计模式之第18章-观察者模式(Java实现)

    设计模式之第18章-观察者模式(Java实现) 话说曾小贤,也就是陈赫这些天有些火,那么这些明星最怕的,同样最喜欢的是什么呢?没错,就是狗仔队.英文的名字比较有意思,是paparazzo,这一说法据说 ...

  2. Head First 设计模式 第2章 观察者模式

    第2章.观察者模式 1.定义: 在对象之间定义一对多关系,当一个对象改变状态时,该对象的依赖会收到通知,并自动更新. 2.介绍 在介绍观察者模式之前,先来说一个日常生活中经常碰到的事(可能现在的人碰到 ...

  3. 设计模式学习之“观察者模式” [C#]

    <深入浅出设计模式>学习笔记第二章 需求: 开发一套气象监测应用,如图: 气象站,目前有三种装置,温度.湿度和气压感应装置. WeatherData对象追踪气象站的数据,并更新到布告板,布 ...

  4. 第二章 OO大原则

    昨天忙了一天,晚上加班到了12点,虽然工作有时候比较累,但是整体来讲还是比较轻松的,国企加上我是今年才毕业的应届生,导致了现在这种情况.工资也真的不算高...但我觉得最开始还是要踏踏实实一点比较好.学 ...

  5. (转)iOS Wow体验 - 第二章 - iOS用户体验解析(2)

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第二章译文精选的第二部分,其余章节将陆续放出.上一 ...

  6. (转)iOS Wow体验 - 第二章 - iOS用户体验解析(1)

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第二章译文精选的第一部分,其余章节将陆续放出.上一 ...

  7. [HeadFirst-JSPServlet学习笔记][第二章:高层概述]

    第二章:高层体系结构 容器 1 什么是容器? servelet没有main()方法.它们受控于另一个Java应用,这个Java应用称为容器(Container) Tomcat就是这样一个容器.Web服 ...

  8. Knockout应用开发指南 第二章:监控属性(Observables)

    原文:Knockout应用开发指南 第二章:监控属性(Observables) 关于Knockout的3个重要概念(Observables,DependentObservables,Observabl ...

  9. 第16章 观察者模式(Oberver Pattern)

    原文  第16章 观察者模式(Oberver Pattern) 观察者模式  概述:   在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依 ...

随机推荐

  1. CentOS8安装本地mail工具-mailx-12.5-29.el8.x86_64

    概述 服务器需要发告警邮件 查找是否已安装 [root@C8-1 ~]# type mail -bash: type: mail: not found [root@C8-1 ~]# which mai ...

  2. Anderson《空气动力学基础》5th读书笔记 第5记——推导二维机翼的空气动力学系数

    机翼的受力分析图 我们知道,空气对一个物体产生的升力和阻力以及力矩源于作用在整个物体上的压力分布和剪切力分布,所以我们分析上图可知(取单位展长的机翼): 对于上表面:                 ...

  3. 最新版Python 3.8.6 版本发布

    Python 3.8.6 发布了,它是 Python 3.8 的第六个维护版本. 3.8 系列的维护版本将每两个月定期更新一次,3.8.7 计划于 2020 年 11 月中旬发布. 随着维护版本的发布 ...

  4. buuctf-misc 菜刀666

    解压出一个666666.pcapng的文件,我们拖进wireshark 因为是菜刀吗?一般都是post连接,于是我们过滤post数据 http.request.method==POST 然后分析流量, ...

  5. 【Python 1-0】10个学习Python的理由以及Python的优势有哪些?

    Python的由来 首发地址 Python的创始人是吉多·范罗苏姆,1989年他在阿姆斯特丹的CWI工作,圣诞节期间,吉多·范罗苏姆为了打发圣诞节的无聊,决定开发一个新的脚本解释程序,作为ABC 语言 ...

  6. 数据恢复软件推荐-easyrecovery绿色破解版(附注册码)免费下载

    easyrecovery破解版专注于PC端存储数据的抢救恢复,软件的整体界面风格和360杀毒有些许相似,没有看起来像牛皮藓的杂乱广告,只有六个功能按键,对应你所遇到的数据丢失状况级别,点击最为适合的功 ...

  7. 如何在 vue 项目里正确地引用 jquery

    转载 2016年11月13日 使用vue-cli构建的vue项目,webpack的配置文件是分散在很多地方的,而我们需要修改的是build/webpack.base.conf.js,修改两处的代码 / ...

  8. OpenCV计算机视觉学习(9)——图像直方图 & 直方图均衡化

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...

  9. 【16】进大厂必须掌握的面试题-100个python面试

    我们整理了Python面试的主要问题清单,分为7个部分: 基本面试问题 OOPS面试问题 基本的Python程序 Python库面试问题 数据分析面试题 选择题(MCQ) 基本的Python面试问题 ...

  10. 工业级4G路由器有哪些优势

    在金融.电力.邮政以及气象等各大行业中有着更为广泛的应用,并受到人们的高度推崇与青睐,那么工业级4G路由器有哪些优势深受用户的喜欢呢? 1.高稳定性 工业级4G路由器在传输和接收数据时具有较高的稳定性 ...