观察者模式

观察者模式的设计原则

为交互对象之间的松耦合设计而努力,使对象之间的相互依赖降到最低。

观察者模式也是对象行为型模式,其意图为:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。其别名又叫:依赖(Dependents), 发布-订阅( Publish-Subscribe)

观察者模式的结构

参与者

  • Subject(目标)——目标知道它的观察者,可以有任意多的观察者观察同一个目标
                          ——提供注册和删除观察者对象的接口。
  • Observer(观察者)——为那些在目标发生改变时需获得通知的对象定义一个更新接口。
  • ConcreteSubject(具体目标)——将有关状态存入各具体观察者对象
                                               ——当它的状态发生改变时,向它的各个观察者发出通知。
  • ConcreteObserver(具体观察者)——维护一个指向具体目标对象的引用
                                                     ——存储有关状态,这些状态应与目标的状态保持一致
                                                     ——实现Observer的更新接口以使自身状态与目标状态保持一致。

协作

  • 当ConcreteSubject发生任何可能导致其观察者与其本身状态不一致的改变时,它将通知它的各个观察者。
  • 在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver使用这些信息以使它的状态与目标对象的状态一致。

    注意发出改变请求的Observer对象并不立即更新,而是将其推迟到它从目标得到一个通知之后。Notify不总是由目标对象调用,它也可被一个观察者或其它对象调用。

使用场景

这里我们来看一下HeadFirstDesignPattern中的例子,气象监测应用:

此系统由三个部分组成:气象站(获取实际数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户)。其中WeatherData对象知道如何跟物理气象站联系并取得数据。WeatherData对象会随即更新三个布告板的显示:目前状况(温度、湿度和气压)、气象统计天气预报

现在我们可以来看具体的实现:

package headfirst.observer.weather;

public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
package headfirst.observer.weather;

public interface Observer {
public void update(float temp, float humidity, float pressure);
}
package headfirst.observer.weather;

public interface DisplayElement {
public void display();
}

//WeatherData对象

package headfirst.observer.weather;

import java.util.ArrayList;

public class WeatherData implements Subject {

	private ArrayList<Observer> observers;
private float temperature;
private float humidity;
private float pressure; public WeatherData() {
observers = new ArrayList<Observer>();
} @Override
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
observers.add(o);
} @Override
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
} @Override
public void notifyObserver() {
// TODO Auto-generated method stub
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
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();
} }

//CurrentConditionsDisplay

package headfirst.observer.weather;

public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity; public CurrentConditionsDisplay(Subject weatherData) {
weatherData.registerObserver(this);
} @Override
public void display() {
// TODO Auto-generated method stub
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
} @Override
public void update(float temp, float humidity, float pressure) {
// TODO Auto-generated method stub
this.temperature = temp;
this.humidity = humidity;
display();
} }

//ForecastDisplay

package headfirst.observer.weather;

public class ForecastDisplay implements Observer, DisplayElement {
private float currentPressure = 29.92f;
private float lastPressure;
private WeatherData weatherData; public ForecastDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
} public void update(float temp, float humidity, float pressure) {
lastPressure = currentPressure;
currentPressure = pressure; display();
} public void display() {
System.out.print("Forecast: ");
if (currentPressure > lastPressure) {
System.out.println("Improving weather on the way!");
} else if (currentPressure == lastPressure) {
System.out.println("More of the same");
} else if (currentPressure < lastPressure) {
System.out.println("Watch out for cooler, rainy weather");
}
}
}

//StatisticsDisplay

package headfirst.observer.weather;

public class StatisticsDisplay implements Observer, DisplayElement {
private float maxTemp = 0.0f;
private float minTemp = 200;
private float tempSum= 0.0f;
private int numReadings;
private WeatherData weatherData; public StatisticsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
} public void update(float temp, float humidity, float pressure) {
tempSum += temp;
numReadings++; if (temp > maxTemp) {
maxTemp = temp;
} if (temp < minTemp) {
minTemp = temp;
} display();
} public void display() {
System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
+ "/" + maxTemp + "/" + minTemp);
}
}

效果

Observer模式允许你独立的改变目标和观察者。你可以单独复用目标对象而无需同时复用其观察者, 反之亦然。它也使你可以在不改动目标和其他的观察者的前提下增加观察者。

下面是观察者模式其它一些优缺点:

  1. 目标和观察者之间的抽象耦合  一个目标所知道的仅仅是它有一系列观察者, 每个都符合抽象的Observer类的简单接口。目标不知道任何一个观察者属于哪一个具体的类。这样目标和观察者之间的耦合是抽象的和最小的。因为目标和观察者不是紧密耦合的,它们可以属于一个系统中的不同抽象层次。一个处于较低层次的目标对象可与一个处于较高层次的观察者通信并通知它,这样就保持了系统层次的完整。如果目标和观察者混在一块,那么得到的对象要么横贯两个层次(违反了层次性),要么必须放在这两层的某一层中(这可能会损害层次抽象)。
  2. 支持广播通信  不像通常的请求,目标发送的通知不需指定它的接收者。通知被自动广播给所有已向该目标对象登记的有关对象。目标对象并不关心到底有多少对象对自己感兴趣;它唯一的责任就是通知它的各观察者。这给了你在任何时刻增加和删除观察者的自由。处理还是忽略一个通知取决于观察者。
  3. 意外的更新  因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外, 如果依赖准则的定义或维护不当,常常会引起错误的更新, 这种错误通常很难捕捉。简单的更新协议不提供具体细节说明目标中什么被改变了,这就使得上述问题更加严重。如果没有其他协议帮助观察者发现什么发生了改变,它们可能会被迫尽力减少改变。

OOP设计模式[JAVA]——02观察者模式的更多相关文章

  1. 《Head First 设计模式》[02] 观察者模式

    1.观察者模式 1.1 形象地认识观察者模式 报社的业务是出版报纸 用户像某家报社订阅了报纸,那么一旦报社有新的报纸,就会送到用户处.只要是订户,就一直会收到新报纸: 当用户不再想看报纸时,取消订阅, ...

  2. OOP设计模式[JAVA]——03职责链模式

    职责链模式 Responsibility of Chain 在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求 ...

  3. OOP设计模式[JAVA]——04命令模式

    命令模式 命令模式的意图 命令模式属于对象的行为模式.别名又叫:Action或Transaction. 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求 ...

  4. 面向对象程序设计(OOP设计模式)-行为型模式之观察者模式的应用与实现

    课程名称:程序设计方法学 实验5:OOP设计模式-行为型模式的应用与实现 时间:2015年12月02日三,第3.4节地点:理 一.实验目的 加深对行为型设计模式的理解以及在开发中的实际应用能力. 二. ...

  5. Java设计模式之《观察者模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6513651.html 观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监 ...

  6. Java设计模式百例 - 观察者模式

    观察者(Observer)模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,主体对象的状态变化会通知所有观察者对象.观察者模式又叫做发布-订阅(Publish/Subscribe ...

  7. 《JAVA设计模式》之观察者模式(Observer)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述观察者(Observer)模式的: 观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Mo ...

  8. java中观察者模式Observable和Observer

    25.java中观察者模式Observable和Observer 如果想要实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口 观察者设计模式 现在很多的 ...

  9. 面向对象程序设计(OOP设计模式)-结构型模式之装饰器模式的应用与实现

    课程名称:程序设计方法学 实验4:OOP设计模式-结构型模式的应用与实现 时间:2015年11月18日星期三,第3.4节 地点:理1#208 一.实验目的 加深对结构型设计模式的理解以及在开发中的实际 ...

随机推荐

  1. ASP.NET UpdatePanel实现点击按钮无刷新且执行js脚本

    [一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/p/3770779.html]  *.aspx: <asp:ScriptManager ID=& ...

  2. easyui源码翻译1.32--PropertyGrid(属性表格)

    前言 继承自$.fn.datagrid.defaults.使用$.fn.propertygrid.defaults重写默认值对象.下载该插件翻译源码 属性表格提供The propertygrid pr ...

  3. SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-007-定义切面的around advice

    一.注解@AspectJ形式 1. package com.springinaction.springidol; import org.aspectj.lang.ProceedingJoinPoint ...

  4. 使用Timer执行定时任务

    一.Timer概述 在Java开发中,会碰到一些需要定时或者延时执行某些任务的需求,这时,我们可以使用Java中的Timer类实现. 二.Timer介绍 Timer是一个定时器类,通过该类可以为指定的 ...

  5. ide远程调试

    这篇写得好:http://qifuguang.me/2015/09/18/IntelliJ%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95%E6%95%99%E7%A8%8B/

  6. 如何关闭win7的ps/2兼容鼠标(触屏版)

    买了一个新电脑联想ThinkPad E555 可是刚拿到是个win10 的系统,用习惯了win7,win0不太好用, 然后帮我刷成了win7,之后一切都好,性能也是让我很满意,但是却关不掉触控板,于是 ...

  7. Good vs Evil

    Good vs Evil Description Middle Earth is about to go to war. The forces of good will have many battl ...

  8. WIP Job > APP-WIP-25191 or Pending Close

    使用 Close Discrete Jobs (FORM) 关闭工单,有一工单的状态一直为PENDING CLOSE 检查 PENDING MATERIAL TRANSACTION ,PENDING ...

  9. "is not on any development teams " Xcode的账号错误问题

    "***@*** is not on any development teams " Xcode现在在"Accounts"中时不时会出现这个提示. 但其他按钮都 ...

  10. JAVA与.NET的相互调用——通过Web服务实现相互调用

    JAVA与.NET是现今世界竞争激烈的两大开发媒体,两者语言有很多相似的地方.而在很多大型的开发项目里面,往往需要使用两种语言进行集成开发.而很多的开发人员都会偏向于其中一种语言,在使用集成开发的时候 ...