观察者模式

泄露秘密 提交于 2020-12-03 17:20:19

观察者模式:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,所有依赖于它的对象都会得到通知并自动更新。

观察者模式适用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用
  • 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变
  • 一个对象必须通知其他对象,而并不知道这些对象是谁

观察者模式组件:

  • Subject(抽象主题):将所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者,抽象主题一般会提供一个可以增加和删除观察者对象的接口。
  • ConcreteSubject(具体主题):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  • Observer(抽象观察者):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  • ConcreteObserver(具体观察者):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

观察者模式组件实例:
抽象主题:

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

抽象观察者:

public interface Observer {
    void update(Subject subject);
}

具体主题:

import java.util.ArrayList;
import java.util.List;

public class Weather implements Subject {
    private List<Observer> observers;

    private double temperature;
    private double humidity;
    private double pressure;

    public Weather() {
        this.temperature = 25.50;
        this.humidity = 26.00;
        this.pressure = 27.15;
        observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        observers.forEach(observer -> observer.update(this));
    }

    public void weatherChanged() {
        notifyObservers();
    }

    public void setWeather(double temperature, double humidity, double pressure) {
        boolean changeFlag = false;
        if (this.temperature != temperature || this.humidity != humidity || this.pressure != pressure)
            changeFlag = true;
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        if (changeFlag) weatherChanged();
    }

    public double getTemperature() {
        return temperature;
    }

    public void setTemperature(double temperature) {
        this.temperature = temperature;
    }

    public double getHumidity() {
        return humidity;
    }

    public void setHumidity(double humidity) {
        this.humidity = humidity;
    }

    public double getPressure() {
        return pressure;
    }

    public void setPressure(double pressure) {
        this.pressure = pressure;
    }

    @Override
    public String toString() {
        return "the temperature is " + this.temperature + "\r\n" +
                "the humidity is " + this.humidity + "\r\n" +
                "the pressure is " + this.pressure;
    }
}

具体观察者:

public class Meteorologist implements Observer {
    private Subject subject;

    @Override
    public void update(Subject subject) {
        this.subject = subject;
        say();
    }

    public void say() {
        System.out.println(toString() + " said : the subject is changed");
        System.out.println(subject.toString());
    }

}

客户端调用:

public class App {
    public static void main(String[] args) {
        Weather weather = new Weather();

        Meteorologist meteorologist1 = new Meteorologist();
        Meteorologist meteorologist2 = new Meteorologist();
        weather.registerObserver(meteorologist1);
        weather.registerObserver(meteorologist2);

        weather.setWeather(25.05, 24.00, 16.10);
    }
}

观察者模式总结:

  • 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
  • 建立了一套良好的触发机制:当被观察者对象改变时,观察者对象可以收到通知。
  • 如果观察者数量比较多,通知时效会比较低(可以考虑采用异步的方式)。
  • 观察者和被观察者如果有循环依赖的话,可能导致系统崩溃。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!