本文介绍23种设计模式之观察者模式。
定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。其实很多地方都用到了观察者模式例如:Listener,Callback等。
描述
- 模式名称:OBSERVER(观察者)
- 类型:对象行为型模式
- 意图:定义对象间的一种一对多的依赖关系 ,当一个对象的状态发生改变时 , 所有依赖于它的对象都得到通知并被自动更新。
- 适用性:
- 当对一个对象的改变需要同时改变其它对象 , 而不知道具体有多少对象有待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之 , 你不希望这些对象是紧密耦合的。
- 效果:
- 优点:
- 目标和观察者间的抽象耦合。
- 支持广播通信。
- 缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
结构
参与者
- Subject(目标)
- 目标知道它的观察者。可以有任意多个观察者观察同一个目标。
- 提供注册和删除观察者对象的接口。
- Observer(观察者)
- 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
- ConcreteSubject(具体目标)
- 将有关状态存入各ConcreteObserver对象。
- 当它的状态发生改变时, 向它的各个观察者发出通知。
- ConcreteObserver(具体观察者)
- 维护一个指向ConcreteSubject对象的引用。
- 存储有关状态,这些状态应与目标的状态保持一致。
- 实现Observer的更新接口以使自身状态与目标的状态保持一致。
举一个例子
公司要和气象局合作,气象局提供温度,湿度,气压的数据,需要设计气象布告板,动态展示数据,并且可以自定义布告板和新增删除布告板的功能。
在此例子中,气象数据就是目标,气象布告板就是观察者目标的父类
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
}
观察者父类
public interface Observer {
void update(WeatherEvent weatherEvent);
}
布告板接口
public interface DisplayEle {
void display();
}
事件对象,用于发送给观察者
public class WeatherEvent {
private double temperature;
private double humidity;
private double pressure;
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;
}
}
天气数据,具体目标
public class WeatherData implements Subject {
private int state;
private WeatherEvent weatherEvent;
private ArrayList<Observer> list;//内部维护一个观察者集合
public WeatherData() {
list = new ArrayList<>();
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public WeatherEvent getWeatherEvent() {
return weatherEvent;
}
public void setWeatherEvent(WeatherEvent weatherEvent) {
this.weatherEvent = weatherEvent;
notifyObserver();
}
@Override
public void registerObserver(Observer observer) {
list.add(observer);
}
@Override
public void removeObserver(Observer observer) {
list.remove(observer);
}
@Override
public void notifyObserver() {
for (int i = 0; i < list.size(); i++) {
Observer observer = list.get(i);
observer.update(weatherEvent);
}
}
}
具体观察者
public class CurrentConditionsDisplay implements Observer,DisplayEle {
private WeatherEvent weatherEvent;
@Override
public void display() {
System.out.println(this.toString()+"===="+weatherEvent.getHumidity()+"==="+weatherEvent.getPressure()+"==="+weatherEvent.getTemperature());
}
@Override
public void update(WeatherEvent weatherEvent) {
this.weatherEvent = weatherEvent;
display();
}
}
jdk 也提供了相似的支持,具体的大家可以参考 java.util.Observable 和 java.util.Observer 这两个类。而且观察者模式不仅可以是subject主动推,也可以observer主动拉去数据,这也是为什么Event对象一般都包含Subject对象的原因。