观察者模式

定义: 一种一对多的依赖模式, 让多个观察者对象同时监听一个主题对象, 主题对象在状态变化时会通知每一个观察者对象, 让其能自动更新状态

结构:

  1. 抽象主题: 抽象主题角色把所有观察者类放在一个集合中, 每个主题可以有任意数量的观察者, 抽象主题提供接口 可以增加和删除观察者
  2. 具体主题: 该角色将有关状态存入具体观察者对象, 在具体主题内部发生改变时, 给所有注册过的观察者发送通知
  3. 抽象观察者: 观察者的抽象类, 定义一个更新接口, 在主题更改时通知自己
  4. 具体观察者: 实现抽象观察者的更新接口, 以便更新状态

实现:

例: 微信公众号, 当公众号更新时, 公众号的订阅者都会收到推送

抽象观察者

/**
 * 观察者类接口
 */
public interface Observer {
    void update(double temprature, double pressure, double humidity);
}

具体观察者

public class Baidu implements Observer {

    private double temprature;
    private double pressure;
    private double humidity;

    public void update(double temprature, double pressure, double humidity) {
        this.temprature = temprature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    private void display() {
        System.out.println("-----------Baidu-----------");
        System.out.println("now temprature is " + temprature);
        System.out.println("now pressure is " + pressure);
        System.out.println("now humidity is " + humidity);
    }
}

抽象主题

/**
 * 观察者模式主类,管理观察者
 */
public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

具体主题

public class WeatherData implements Subject {

    private double temprature;
    private double pressure;
    private double humidity;
    private List<Observer> observers;

    public WeatherData() {
        observers = new ArrayList<Observer>();
    }

    /**
     * 当数据又改变时会通知所有的观察者
     */
    public void setData(double temprature, double pressure, double humidity) {
        this.temprature = temprature;
        this.pressure = pressure;
        this.humidity = humidity;
        notifyObservers();
    }

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

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

    public void notifyObservers() {
        for(Observer observer : observers) {
            observer.update(this.temprature, this.pressure, this.humidity);
        }
    }
}

Main

/**
 * 观察者模式
 * 优点:
 * 1. 降低了目标与观察者之间的耦合关系, 两者之间是抽象耦合关系
 * 2. 被观察者发送通知, 所有注册的观察者都会收到
 *
 * 缺点:
 * 1. 如果观察者过多, 那么所有观察者收到通知会耗时过长
 * 2. 如果被观察者有循环依赖, 被观察者发送通知时会使观察者循环调用, 导致系统崩溃
 */
public class Main {
    public static void main(String[] args) {
        WeatherData subject = new WeatherData();
        Observer observer = new Baidu();
        subject.registerObserver(observer);
        subject.setData(35.0, 40.0, 15.0);
    }
}

使用场景

  1. 对象间存在一对多关系, 一个对象的状态改变会影响其他对象
  2. 当一个抽象模型有两个方面, 其中一个方面依赖与另一个方面