观察者模式类似于报纸和杂志的订阅
- 报社的业务就是出版报纸。
- 向某家报社订阅报纸,只要他们有新报纸出版,就会给你发送。只要你是他们的订户,你就会一直收到新报纸。
- 当你不再想看新报纸的时候,取消订阅,他们就不会再送新报纸。
- 只要报社还在运营,就会一直有人向他们订阅报纸或取消订阅报纸。
出版者+订阅者=观察者模式
出版者成为主题(Subject),订阅者成为观察者(Observer)。
定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会受到通知并自动更新。
以气象观测站为例,由WeatherDate负责追踪目前的天气状况(温度,湿度,气压),建立一个应用,有三种布告板分别显示目前的天气状,气象统计及简单的预报。
当WeatherData获得最新的数据时,三种布告板同时更新数据。
关系图
使用idea简单生成,无法再次编辑不够详细。


public interface Subject {
/**
* 这两个方法都需要一个观察者对象作为参数
* 该观察者是用来注册或者被删除的
* @param o
*/
void registerObserver(Observer o);
void removeObserver(Observer o);
/**
* 当主题状态改变时,这个方法会被调用,以通知所有的观察者
*/
void notifyObservers();
}
public interface Observer {
/**
* 所有的观察者都需要实现此方法,以实现观察者接口
* 当主题监测的数据发送改变时,主题会把这些状态值当做方法的参数,传送给观察者
* @param temp
* @param humidity
* @param pressure
*/
void update(float temp, float humidity, float pressure);
}
public interface DisplayElement {
/**
* 观察者必须实现此接口,强行使用外观显示方法
*/
void display();
}
在WeatherData中实现主题接口
public class WeatherDate implements Subject {
private ArrayList<Observer> observer;
private float temoerature;
private float humidity;
private float ressure;
public WeatherDate() {
observer = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
observer.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observer.indexOf(o);
if (i >= 0) {
observer.remove(i);
}
}
/**
* 遍历所有观察者
* 通知他们更新数据
*/
@Override
public void notifyObservers() {
for (int i = 0; i < observer.size(); i++) {
Observer observer = this.observer.get(i);
observer.update(temoerature, humidity, ressure);
}
}
public void measuremensChanged() {
notifyObservers();
}
public void setMeasurements(float temoerature, float humidity, float ressure) {
this.temoerature = temoerature;
this.humidity = humidity;
this.ressure = ressure;
measuremensChanged();
}
}
定义布告栏实现Observer接口和外观显示的DisplayElement接口
只实现其中一个,其余类似
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
this.weatherData.registerObserver(this);
}
/**
* 更新
*
* @param temp
* @param humidity
* @param pressure
*/
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
/**
* 显示
*/
@Override
public void display() {
System.out.println("1,当前布告板: 温度" + temperature + "度,湿度" + humidity + "%");
}
}
测试类
public class Test {
public static void main(String[] args) {
WeatherDate weatherDate = new WeatherDate();
//注册为观察者
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherDate);
//主题更新数据
weatherDate.setMeasurements(20, 60, 50);
}
}
网友评论