观察者模式——HeadFirst 设计模式学习笔记

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

推拉两种获取数据方式:

  • 推:可以把数据当做数据对象的方式传给观察者
  • 拉:通过getter方法获取数据

设计原则:

  • 为了交互对象之间的松耦合而努力,让我们建立有弹性的OO系统

特点:

  • 观察者模式定义了对象之间的一对多关系
  • 当一个对象的状态改变了,其他的依赖者都会收到通知

松耦合的威力:

  • 两个对象之间松耦合,他们可以交互,但是不太清楚彼此的细节
  • 观察者模式提供了一种对象设计,让主题和观察者之间松耦合
  • 主题只知道观察者对象实现了某个借口,而不知道观察者具体的细节
  • 我们可以随时添加和删除观察者

适用性

  1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  2. 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  3. 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

举例:

  • 实现一个气象监测系统,此系统的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)
  • 我们可以通过MeasurementsChanged()方法通知各个布告版
    •  1 public void MeasurementsChanged()
       2  {
       3         float temp = GetTemperature();
       4         float humidity = GetHumidity();
       5         float pressure = GetPressure();
       6     //三个布告版
       7         currentConditionDisplay.update(temp, humidity, pressure);
       8         statisticsDisplay.update(temp, humidity, pressure);
       9         forecastDisplay.update(temp, humidity, pressure);
      10  }
  • 然而布告版的数量是不确定的,可能在某个时刻增加,可能在某个时刻减少,而且种类不同,如果使用如上代码,当布告版变化时代码修改维护量巨大
  • 使用观察者模式修改设计

代码实现

1、主题接口

  • 1 public interface Subject {  
    2     public void registerObserver(Observer o);  
    3     public void removeObserver(Observer o);  
    4 public void notifyObservers(); 5 }

2、观察者接口

1 public interface Observer {  
2     public void update(float temp, float humidity, float pressure);  
3 }

3、主题实现

 1 public class WeatherData implements Subject {  
 2     private ArrayList observers;  
 3     //temperature、humidity、pressure就是WeatherData的“状态”  
 4     private float temperature;  
 5     private float humidity;  
 6     private float pressure;  
 7       
 8     public WeatherData() {  
 9         observers = new ArrayList();  
10     }  
11       
12     public void registerObserver(Observer o) {  
13         observers.add(o);  
14     }  
15       
16     public void removeObserver(Observer o) {  
17         int i = observers.indexOf(o);  
18         if (i >= 0) {  
19             observers.remove(i);  
20         }  
21     }  
22       
23     public void notifyObservers() {  
24         for (int i = 0; i < observers.size(); i++) {  
25             Observer observer = (Observer)observers.get(i);  
26             observer.update(temperature, humidity, pressure);  
27         }  
28     }  
29       
30     public void measurementsChanged() {  
31         notifyObservers();  
32     }  
33       
34     public void setMeasurements(float temperature, float humidity, float pressure) {  
35         this.temperature = temperature;  
36         this.humidity = humidity;  
37         this.pressure = pressure;  
38         measurementsChanged();  
39     }  
40       
41     public float getTemperature() {  
42         return temperature;  
43     }  
44       
45     public float getHumidity() {  
46         return humidity;  
47     }  
48       
49     public float getPressure() {  
50         return pressure;  
51     }  
52 }  

4、观察者实现

 1 public class CurrentConditionsDisplay implements Observer, DisplayElement {  
 2     private float temperature;//温度  
 3     private float humidity;//湿度  
 4     private Subject weatherData;  
 5       
 6     public CurrentConditionsDisplay(Subject weatherData) {  
 7         this.weatherData = weatherData;  
 8         weatherData.registerObserver(this);  
 9     }  
10     //推数据,这里只使用到了前两个参数  
11     public void update(float temperature, float humidity, float pressure) {  
12         this.temperature = temperature;  
13         this.humidity = humidity;  
14         display();  
15     }  
16       
17     public void display() {  
18         System.out.println("Current conditions: " + temperature   
19             + "F degrees and " + humidity + "% humidity");  
20     }  
21 }  

要点

  1. 观察者模式定义了对象之间一对多的关系。
  2. 主题(也就是可观察者)用一个共同的接口来更新观察者。
  3. 观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口。
  4. 使用此模式时,你可从被观察者处推或拉数据。
  5. 有多个观察者时,不可以依赖特定的通知次序。
  6. Java有多种观察者模式的实现,包括了通用的java.util.Observable。
  7. 要注意java.util.Observable实现上所带来的一些问题。Swing大量使用观察者模式,许多GUI框架也是如此。
    1. Java内置的观察者模式中Observable是一个类,你必须设计一个类去继承它。如果某类相同时具有Observable类和另一个超类的行为,就无法实现,因为java不支持多继承。
    2. Observable API将setChanged()方法保护了起来,除非继承自Observable类,否则无法创建Observable实例组合到自己的对象中,也违背了面向对象设计的第二个原则:多用组合,少用继承。
  8. 此模式也被应用在许多地方,例如:JavaBeans、RMI。
原文地址:https://www.cnblogs.com/HectorHou/p/5977905.html