观察者模式定义了一种一对多的依赖关系,当一个对象改变状态时,他的所有依赖者都会收到通知并更新数据。
比如我们常见的设置监听,button.setOnClickListener也算是观察者的一种。
核心关注点
观察者与被观察者是松耦合的,被观察者只需要知道,观察者都实现了统一的接口,都提供了update的方法。只要接口不变,改变任何一方的内容,都不会对另一方造成影响。
被观察者中持有观察者的list,发生数据变化就通知到list中的所有观察者,注意解除观察的时候及时移除观察者,避免内存泄漏.
气象站的故事情景
X公司与气象台合作,气象台会提供一个WeatherData对象,该对象会追踪当前的天气状况,温度,湿度,气压三种。要求X公司提供系统,可以接入不同的布告板展示数据,要求第三方任意公司都可以创建布告板,接入并展示气象台的数据。
我们定义了主题接口(被观察者接口),声明了添加观察者,移除观察者,通知变化的方法。同时定义一个观察者接口,声明一个更新的方法。
图中多了display接口,考虑到不同的布告板,显示不同的样式,效果,所以这里才有了该接口。
interface Observer {
void update(float temp, float humidity, float pressure);
}
interface DisplayElement {
void display(float temp, float h, float p);
}
public interface Subject {
void registObserver(Observer observer);
void removeOBserver(Observer observer);
void notifyOBservers();
}
数据监控对象
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public synchronized void registObserver(Observer observer) {
if (observers.contains(observer)) {
return;
}
observers.add(observer);
}
@Override
public synchronized void removeOBserver(Observer observer) {
if (!observers.contains(observer)) {
return;
}
observers.remove(observer);
}
@Override
public void notifyOBservers() {
for (Observer o : observers) {
o.update(temperature, humidity, pressure);
}
}
private void measurementChanged() {
notifyOBservers();
}
public void setMeasurements(float t, float m, float p) {
this.temperature = t;
this.humidity = m;
this.pressure = p;
measurementChanged();
}
}
布告板
class CurrentConditionDisplay implements Observer, DisplayElement {
private WeatherData mWeatherData;
public CurrentConditionDisplay(WeatherData weatherData) {
this.mWeatherData = weatherData;
weatherData.registObserver(this);
}
@Override
public void display(float temp, float h, float p) {
System.out.println("布告板展示数据:温度:" + temp + " 湿度是:" + h + " 气压是:" + p);
}
@Override
public void update(float temp, float humidity, float pressure) {
//获取到了数据,
System.out.println("布告板收到数据更新的通知了");
display(temp, humidity, pressure);
}
public void destroy() {
mWeatherData.removeOBserver(this);
mWeatherData = null;
}
}
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);
weatherData.setMeasurements(30f, 20f, 1.0f);
java中内置了观察者模式,但是,java内置的Observable是一个类,在java单继承的情况下,一旦继承了Observable类,就无法继承其他类了。并且内部notifyObservers的方法,需要在状态changed为true的情况下才会发送通知,而该setChanged的方法是protected的,如果不是其子类就无法调用更改状态。属实是坑。