观察者模式
定义: 一种一对多的依赖模式, 让多个观察者对象同时监听一个主题对象, 主题对象在状态变化时会通知每一个观察者对象, 让其能自动更新状态
结构:
- 抽象主题: 抽象主题角色把所有观察者类放在一个集合中, 每个主题可以有任意数量的观察者, 抽象主题提供接口 可以增加和删除观察者
- 具体主题: 该角色将有关状态存入具体观察者对象, 在具体主题内部发生改变时, 给所有注册过的观察者发送通知
- 抽象观察者: 观察者的抽象类, 定义一个更新接口, 在主题更改时通知自己
- 具体观察者: 实现抽象观察者的更新接口, 以便更新状态
实现:
例: 微信公众号, 当公众号更新时, 公众号的订阅者都会收到推送
抽象观察者
/**
* 观察者类接口
*/
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);
}
}
使用场景
- 对象间存在一对多关系, 一个对象的状态改变会影响其他对象
- 当一个抽象模型有两个方面, 其中一个方面依赖与另一个方面