zoukankan      html  css  js  c++  java
  • 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接口),主题并不需要知道观察者的具体类是谁和其他的细节。想要增加观察者,只需要实现这个接口。运行时,随时增加删除,主题并不会受到影响。我们可以独立的复用主题或者观察者的代码(在类里实现这些接口即可),改变主题或观察者的一方并不会影响到另一方,因为二者并非紧耦合。

  • 相关阅读:
    codeforces 820 D. Mister B and PR Shifts(思维)
    codeforces 820 C. Mister B and Boring Game(找规律)
    玲珑杯 1137
    codeforces 817 D. Imbalanced Array(单调栈+思维)
    Atcoder D
    Atcoder C
    Atcode B
    codeforces 816 E. Karen and Supermarket(树形dp)
    codeforces 816 D. Karen and Test(逆元+思维+组合数)
    codeforces 816 C. Karen and Game(模拟+思维)
  • 原文地址:https://www.cnblogs.com/badboyf/p/6186119.html
Copyright © 2011-2022 走看看