这篇文章来总结一下观察者模式,首先,观察者模式的定义:
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
如上图所示,Observer作为观察者,subject主题做为被观察者,打个比方,主题是一家报社,它有注册用户,移除用户,通知用户的功能,而用户作为观察者只需要等待报社定期发报纸就行了(通知)。
下面我们结合代码来近距离体验一下这个模式的威力所在
public class WeatherData implements Subject {
private ArrayList observers; //观察者列表
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
//将观察者加入到观察者列表中去,这里的入参书Observer类型的,并不是具体的观察者,所以被观察者并不需要知道观察者是什么
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
//通知观察者列表中的所有观察者
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
//监测到改变就通知观察者
public void measurementsChanged() {
notifyObservers();
}
...
}
这个实现了主题(subject)的类就是具体的被观察者了,它所做的工作就是当状态改变了就通知观察者列表中的所有观察者,而观察者列表所加入或移除的观察者类型,主题并不知道。
public class HeatIndexDisplay implements Observer, DisplayElement {
float heatIndex = 0.0f;
private WeatherData weatherData; //实例化具体的被观察者
public HeatIndexDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this); //将自己加入观察者列表
}
public void update(float t, float rh, float pressure) {
heatIndex = computeHeatIndex(t, rh);
display();
}
...
}
这是一个实现了Observer的具体观察者,这里利用了组合,得到了被观察者的实例然后调用其rigister方法,将本类加入到观察者列表中,如果具体的被观察者监测到了外界状态改变,就会通知所有的观察者,并调用它们的update方法。
从具体的代码可以看出来,观察者模式通过向上转型(注册观察者那里直接声明Observer的类型),对接口编程(抽象出subject和observer这两个接口)实现了观察者与被观察者的解耦,这样一来,增加观察者就不用修改具体主题的代码了。真正做到了对修改关闭,对扩展开放。