最近在读《Head First设计模式》一书,此系列会引用源书内容,但文章内容会更加直接,以及加入一些自己的理解。

  观察者模式(有时又被称为模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

  引子

  我们的公司刚刚你拿下了一个中国气象局的一个招标,负责建立北京市的气象观测站。该气象站必须建立在中国气象局专利申请中的WeatherData对象上,有WeatherData对象负责追踪目前的天气状况,(由于本文只做例子,只追踪温度、湿度、气压)。气象站提出应用的要求:

  1、我们公司能建立一个应用,有三种布告板,可以显示实时天气状况、气象统计、以及简单的预报。

  2、当WeatherData对象获得最新的测量数据时,三种布告板必须实时更新。

  3、我们的气象站是可以扩展的,气象站希望可以公布一组API(接口),好让其他开发人员可以自己写出自己的气象公告板,并插入此应用

  初步设计

  1、首先根据气象站的需求,我们画一个示意图。

  

  WeatherData对象知道如何跟物理气象站联系,当数据跟新时,WeatherData对象从气象站获得数据,WeatherData对象随机更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报,所以我们目前的主要任务是,利用WeatherData对象从气象站获取数据,并跟新三个布告板。

  在设计之前,我们要看一看气象站给我们WeatherData类(此处只做示意,代码后面会变得完整)

public class WeatherData {//下面的三个方法获取温度、湿度、以及压力public float getTemperature(){temperature=获取温度;return temperature;}public float getHumidity(){temperature=获取湿度;return humidity;}public float getPressure(){temperature=获取压力;return pressure;}//一旦气象测量更新、此方法就会被调用public void measurementsChanged(){}

  好了,到此为止我们已经知道了最终的设计要求以及气象站给我们的WeatherData类,下面我们就要开始设计我们的应用,根据我们知道的东西,我们可以先来一个不完整的初版,我们现在WeatherData中增加一些方法(不着急先写出方法的具体内容,只要写出一个方法名,记得它的功能即可)

public class WeatherData {    //下面的三个方法获取温度、湿度、以及压力public float getTemperature(){temperature=获取温度;return temperature;}public float getHumidity(){temperature=获取湿度;return humidity;}public float getPressure(){temperature=获取压力;return pressure;}//一旦气象测量更新、此方法就会被调用public void measurementsChanged(){float temp = getTemperature();float humidity = getHumidity();float pressure = getPressure();

     currentConditionsDisplay.update(temp,humidity,pressure);     statisticsDiaplay.updata(temp,humidity,pressure);     forecastDisplay.update(temp,humidity,pressure);}

  这是我们第一次设计的程序,由于我们已经开始准备用设计模式了,所以我们可以看看我们目前的代码中是不是有还可以改进的地方,首先,我们看到了三个公告板都有update方法,那我们就可以把这个方法

抽取成一个接口,这样我们每次增加公告板时直接实现此接口就可以,其次,本次我们讨论的是观察者模式,那我们的引子就先说到这,我们开始看看什么是观察者设计模式,我们了解完观察者设计模式后,我们

再回到我们的引子,完成设计。

  认识观察者设计模式

  在生活中,订阅报纸就是就是一个观察者设计模式,报社的业务就是出版报纸,当你订阅了某家报社的报纸,只要报社有了新的报纸出版,他们就会给你送来,只要你是他们的订户,你就一定会收到报

纸,当你不想在看这家报纸时,你就可以取消订阅,他们就不会再送来新报纸。其实,出版社+订阅者就等于观察者模式,只是在这个模式里,出版社叫做“主题(Subject)”,订阅者叫做观察者"(Observer)”,如果

你还没有看懂,那我们来看下面这个图:

  

  图中主题对象管理者int数据,狗对象、猫对象、老鼠对象订阅了主题,一旦主题对象发生改变,就会给这些订阅了的对象发送数据,鸭子对象没有订阅主题,就不会接收到数据。

  有一天,鸭子对象突然对主题对象管理的数据起了兴趣,它就需要过去告诉主题,我对你的数据改变有兴趣,一有变化请告诉我,这就是“订阅”的过程,在这之后,鸭子对象就是正式

的观察者了,以后主题管理的数据再有改变就会告诉鸭子对象。

  又有一天,老鼠对象对主题说,你管理的数据我观察太久了,我不想再当你的观察者了,这时主题就删掉老鼠对象,每当数据再变化时,老鼠对象就不会接收到数据。

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

  下面是便是定义观察者设计模式的类图:

  

  观察者设计模式应用到我们的气象站中

  我们已经基本了解了观察者设计模式,那我们就可以回到我们的引子完成原来的设计

  初步思考

  通过我们在上面分析的观察者设计模式,我们发现这是模式是一对多的关系,每当一改变时,就会给多发送改变的数据,而在我们的气象站设计中,正是一对多的关系,一就是我们的WeatherData数据

多就是显示的布告板,而不同的布告板有相同和不同的方法,我们可以把相同的部分抽取成接口,实现代码的复用,那么下面就让我们参照上面观察者设计模式的类图画一下我们气象站的设计类图。(自己

先尝试一下哟)

  设计气象站

  

    实现气象站

    根据上面的类图,我们就可以完善我们的代码啦

    Subject类的接口及WeatherData实现

package com.frank.observe.subject;
import com.frank.observe.observer.Observer;public interface Subject {  //主题注册、删除、通知观察者方法public void registerObserver(Observer o);public void removeObserver(Observer o);public void notifyObserver();//信息改变时执行方法public void measurementsChanged();
}

package com.frank.observe.subject;
import java.util.ArrayList;
import com.frank.observe.observer.Observer;public class WeatherData implements Subject {  //WeatherData实现了Subject方法private ArrayList<Observer> observers;  //包含温度、湿度、压力private float temperature;private float humidity;private float pressure;//构造器创建观察者们的集合public WeatherData(){observers = new ArrayList<Observer>();}//接口方法@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {int i = observers.indexOf(o);if(i>=0){observers.remove(o);}}@Overridepublic void notifyObserver() {for(int i = 0;i<observers.size();i++){Observer observer = observers.get(i);observer.update(temperature, humidity, pressure);}}@Overridepublic void measurementsChanged() {notifyObserver();}//WeatherData自己的set方法,一会测试时在test中改变数据源public void setMeasurements(float temperature,float humidity, float pressure){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;measurementsChanged();}}

   Observer类的接口以及CurrentConditionDisplay实现

package com.frank.observe.observer;
//Observer接口中更新数据的方法
public interface Observer {public void update(float temp,float humidity,float pressure);
}

package com.frank.observe.observer;
import com.frank.observe.display.DisplayElement;
import com.frank.observe.subject.Subject;
import com.frank.observe.subject.WeatherData;
//显示板要实现Observer以及DisplayElement接口(及公共方法)
public class CurrentConditionDisplay implements Observer, DisplayElement {private float temprature;private float humidity;  //将weatherData作为自己的成员变量private Subject weatherData;//在带参构造器中将自己注册到weatherData中public CurrentConditionDisplay(Subject weatherData){this.weatherData=weatherData;weatherData.registerObserver(this);}//接口的更新方法@Overridepublic void update(float temp, float humidity, float pressure) {this.temprature=temp;this.humidity=humidity;     //接口的显示方法display();}@Overridepublic void display() {System.out.println("current conditions" +temprature+"F degrees and"+humidity+"% humidity");}}

  DisplayElement接口

package com.frank.observe.display;public interface DisplayElement {public void display();
}

  Test方法

package com.frank.observe.test;
import com.frank.observe.observer.CurrentConditionDisplay;
import com.frank.observe.subject.WeatherData;public class Test {public static void main(String[] args) {     //新建一个主题WeatherData weatherData = new WeatherData();     //新建一个公告板并将自己注册到主题中CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData);     //每当主题更新数据时发送给观察者,观察者显示在公告板中weatherData.setMeasurements(80, 60, 30.4f);weatherData.setMeasurements(82, 70, 29.2f);weatherData.setMeasurements(78, 90, 29.2f);}}

  结果

current conditions80.0F degrees and60.0% humidity
current conditions82.0F degrees and70.0% humidity
current conditions78.0F degrees and90.0% humidity

  总结

   要点:

OO基础:抽象

OO原则:封装变化、多用组合,少用继承、针对接口编程,不针对实现编程

OO模式:观察者设计模式----在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会受到通知,并自动更新(后面的系列会看到其代表人物--MVC)

  

转载于:https://www.cnblogs.com/FrancisLiu/p/8728070.html

《Head First设计模式》批注系列(一)——观察者设计模式相关推荐

  1. java观察者设计模式_Java中的观察者设计模式

    java观察者设计模式 在本教程中,我们将讨论Observer设计模式. 观察者模式有两个主要方面- 主题和观察者 . 当我们的系统有多个对象(称为观察者)时 ,将使用一个模式,即依赖于一个特定对象( ...

  2. java监听设计模式----得-先理解观察者设计模式

    监听模式有三个概念:事件源.事件.监听器 讲解场景:熊孩子.妈妈---爸爸--爷爷.吃饭--睡觉--打游戏--学习: 其中熊孩子是被观察者即事件源:妈妈---爸爸--爷爷是观察者即监听器:吃饭--睡觉 ...

  3. 行为设计模式 - 观察者设计模式

    行为设计模式 - 观察者设计模式 观察者模式是行为设计模式之一.当您对对象的状态感兴趣并希望在有任何更改时收到通知时,观察者设计模式非常有用.在观察者模式中,监视另一个对象状态的对象称为Observe ...

  4. Net设计模式实例系列文章总结[转]

    1 什么是设计模式 设计模式是对在软件设计过程中重复出现的问题提出了一种比较好的解决方案.正如一位专家所说:设计模式是对程序设计人员经常遇到的设计问题的可再现的解决方案(The Smalltalk C ...

  5. 设计模式: 自己手动实现一个观察者设计模式

    观察者模式: 定义了对象之间的一对多依赖,这样一来.当一个对象(被观察者)改变状态时,它的全部依赖者(观察者)都会收到通知并自己主动更新. 在观察者模式中,会改变的是主题的状态,以及观察者的数目和类型 ...

  6. 探究netty的观察者设计模式

    javadoc笔记点 观察者的核心思想就是,在适当的时机回调观察者的指定动作函数 我们知道,在使用netty创建channel时,一般都是把这个channel设置成非阻塞的模式,这意味着什么呢? 意味 ...

  7. 观察者设计模式二:回调函数

    在上篇博客中具体介绍了观察者设计模式在异步短信发送中的应用场景,但是,在具体的业务中短息发送使用那种方式则会令代码很不友好: 这里我使用的是回调函数的方式来实现这个业务需求: 在具体的业务场景中,我们 ...

  8. 简单的对象监听器 观察者设计模式

    该代码实现了一个可以注册监听类的类,如果注册了监听类,那么在类的一个方法执行前会执行监听类的方法.并且该监听类方法的参数就是被监听对象. 监听类就是事件监听器,被监听对象就是事件源,事件监听器的参数就 ...

  9. 常用的设计模式——观察者设计模式?和发布者-订阅者设计模式的区别

    1. 观察者设计模式 观察者把自己"绑定"至目标,当目标发生变化时,目标"通知"观察者,然后观察者进行相应操作.你有没有觉得这种设计模式更像发布-订阅设计模式? ...

最新文章

  1. Eclipse中的checkstyle插件
  2. 最牛啤的java,没有之一~
  3. WCF:Maximum number of items that can be serialized or deserialized in an object graph is '65536'.
  4. php简单的mysql类_超简单php mysql数据库查询类
  5. Apache Hadoop下一代MapReduce框架(YARN)简介 (Apache Hadoop NextGen MapReduce (YARN))
  6. 2009年1月5日 洛基网络教室听课笔记
  7. java 异常面试问题_Java异常面试问答
  8. Sublime Text2.0.2注册码,添加python编译系统:
  9. 实用———springmvc接收参数校验
  10. RHEL5 配置yum
  11. 文本转语音(TTS)工具Balabolka
  12. 假设检验 python_数据清洗、假设检验
  13. 中望cad文字显示问号怎么办_中望CAD钢筋符号显示为问号怎么办?
  14. 传感器极性NPN和PNP区别!!!
  15. echarts的x轴y轴的颜色改变
  16. 大数据给交通行业带来的五大变革
  17. Android - 接收、监听系统短信广播
  18. Android关闭输入法
  19. CodeForces - 1139C Edgy Trees (快速幂+dfs)
  20. MT4/MQL4入门到精通EA教程第六课-MQL语言常用函数(六)-常用订单功能函数

热门文章

  1. 迷你5和迷你4区别_可变大小的视频迷你批处理
  2. 逻辑回归是分类还是回归_分类和回归:它们是否相同?
  3. 深圳多管齐下破解“融资难”
  4. 单片机小白学步系列(十七) 单片机/计算机系统概述:核心模块
  5. 底部检测的do...while循环
  6. java spring redis_spring配置redis(xml+java方式)
  7. mysql json坑_使用mysql innodb 使用5.7的json类型遇到的坑和解决办法
  8. nosuchelementexception 是什么异常_有甲状腺结节的人为什么越来越多?
  9. mac显示网速_Mac网络流量监控工具——NetWorker pro
  10. qpsk 锁相环_本科毕业设计课题—QPSK相干解调的MATLAB仿真(4)