设计模式 - 观察者模式
概念
观察者模式又称为发布订阅模式,其原理和报纸的订阅一样,在主题(Subject)发生变更的时候,主动通知观察者(Observer)。
定义
观察者模式定义了对象之间一对多的的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收单通知并自动更新。
主题对象和观察者对象定义了一对多的关系。观察者依赖于此主题,主要主题的状态一发生变化,就会主动通知观察者,观察者的状态也可能因为收到的通知而改变。
面向接口设计的框架图
面对接口的设计:
松耦合
对于观察者的一切,主题只知道观察者实现了某个接口(也就是Observer接口),主题并不需要知道观察者具体类是谁,做了什么,实现了那些细节
任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现了Observer接口的对象列表,所以我们可以随时增加或者减少观察者,事实上在runtime的时候,我们可以用新的观察者取代现有的观察者,主题也不会受到任何影响。
有新的类型的观察者出现时,主题代码并不需要为了兼容新的类型的观察者而做修改,只要观察者实现了Observer接口,主题所需要做的只是注册一个观察者,仅此而已,这就是松耦合的威力。
松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。
设计原则
为了交互对象之间的松耦合设计而努力
代码Demo:设计一个气象站
主题接口:
//主题接口
public interface Subject {
//注册观察者
void registerObserver(Observer o);
//移除观察者
void removeObserver(Observer o);
//通知所有观察者
void notifyObservers();
}
观察者接口:
//观察者接口
public interface Observer {
//接收通知
void update(float temperature, float humidity, float pressure);
}
具体气象站主题对象:
//具体的气象站主题对象
public class WeatherData implements Subject {
//观察者列表
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
observers.remove(i);
}
@Override
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void merseurementChanged() {
notifyObservers();
}
public void setMesurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
merseurementChanged();
}
}
天气观察者的展示接口:
//气象站观察者都拥有展示接口
public interface DisplayElement {
void display();
}
当前天气观察者:
//具体的观察者对象,订阅气象站主题,获取当前气象信息
public class CurrentConditionDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private float pressure;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("现在天气状况 temperature:" + temperature + ", humidity:" + humidity + ", pressure:" + pressure);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
}
其他的观察者:
//其他的观察者
public class otherDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private float pressure;
private Subject weatherData;
public StatisticsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("其他天气状况 temperature:" + temperature + ", humidity:" + humidity + ", pressure:" + pressure);
}
@Override
public void update(float temperature, float humidity, float pressure) {
//TODO - 对temperature, humidity, pressure做一些处理,例如
this.temperature = temperature - 0.1f;
this.humidity = humidity - 0.1f;
this.pressure = pressure - 0.1f;
display();
}
}
测试样例:
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
OtherDisplay otherDisplay = new OtherDisplay(weatherData);
weatherData.setMesurements(80, 65, 40.4f);
weatherData.setMesurements(78, 70,29.2f);
}
}
测试结果: