观察者模式:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,所有依赖于它的对象都会得到通知并自动更新。
观察者模式适用场景:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变
- 一个对象必须通知其他对象,而并不知道这些对象是谁
观察者模式组件:
- 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);
}
}
观察者模式总结:
- 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
- 建立了一套良好的触发机制:当被观察者对象改变时,观察者对象可以收到通知。
- 如果观察者数量比较多,通知时效会比较低(可以考虑采用异步的方式)。
- 观察者和被观察者如果有循环依赖的话,可能导致系统崩溃。
来源:oschina
链接:https://my.oschina.net/u/3057088/blog/4772762