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 > 0) {
      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(80, 65, 30);
    display.display();
  }
}

这里存在的一个问题是三个属性最好封装成一个对象,这样在以后新增其他属性时候方便修改。

一对多的关系:利用观察者模式,主题是一个有状态的对象,并且可以修改这些状态。另一方面,观察者也有一自己的状态,但是观察者的状态使用主题的状态来更新或显示。这样主题与观察者就能有一个一对多的关系。这里,主题是真正拥有对象的人,观察者只是主题的依赖者。

观察者模式提供了一种对象设计,让主题和观察者之间松耦合:
关于观察者的一切,主题只知道观察者实现了某个接口(Observer接口),主题并不需要知道观察者的具体类是谁和其他的细节。想要增加观察者,只需要实现这个接口。运行时,随时增加删除,主题并不会受到影响。我们可以独立的复用主题或者观察者的代码(在类里实现这些接口即可),改变主题或观察者的一方并不会影响到另一方,因为二者并非紧耦合。

原文地址:https://www.cnblogs.com/badboyf/p/6186119.html