借用天气观测站的例子实现观察者模式
首先需要有一个检测天气数据的 WeatherData类,此类实现了 Subject接口。Subject接口作为观察者模式中的主体,内部定义了三个方法,分别是:
注册观察者
1. public void registerObserver(Observer observer);
移除观察者
2. public void removeObserver(Observer observer);
通知观察者更新
3. public void notifyObservers();
所有的观察者类都实现了Observer接口,此接口内部有一个update() 方法用来更新数据。
下面就要具体的Subject接口:
public class WeatherData implements Subject {
// 所有的观察者都放入这个对象中
private ArrayList observers;
// 实时监测到的气温
private float temperature;
// 湿度数据
private float humidity;
// 压强数据
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
@Override
// 注册观察者即是将实现了Observer接口的对象放入观察者表中
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
// 移除观察者即是将观察者对象移除观察者表中
public void removeObserver(Observer observer) {
int i = observers.indexOf(observer);
if (i >= 0) {
observers.remove(i);
}
}
@Override
// 将更新的数据通知给所有注册在观察者表中的对象,循环表中的每一个对象,调用其update()方法
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer o = (Observer) observers.get(i);
o.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
// 设置完数据后,通知更新
public void setMeasurements(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
不同的观察者需要不同的天气数据类型,但是他们都需要展示其中的数据,所以定义DisplayElement接口内部包含display() 方法。所有观察者实现 Oberver接口的同时也要实现DisplayElement接口,这样才具备展示数据的能力。
public class CustomDisplay implements Observer, DisplayElement {
// 由于此类只需要温度数据,所以只需要温度的字段
private float temperature;
@Override
public void display() {
System.out.println("Current Temperature is " + temperature + " ℃");
}
@Override
public void update(float temp, float humidity, float pressure) {
temperature = temp;
display();
}
}
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
// 创建此观察者时,提供主体对象,实现注册
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current Conditions: " + temperature + " ℃ " + humidity +
" % humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
}
测试实例运行
public static void main(String[] args) {
// 创建数据主体
WeatherData weatherData = new WeatherData();
// 创建观察者,同时完成注册
CurrentConditionsDisplay conditionsDisplay =
new CurrentConditionsDisplay(weatherData);
// 创建另一个观察者
CustomDisplay customDisplay = new CustomDisplay();
// 注册观察者
weatherData.registerObserver(customDisplay);
// 设置数据
weatherData.setMeasurements(23.5f, 79f, 30.4f);
// 移除观察者
weatherData.removeObserver(customDisplay);
weatherData.setMeasurements(30.0f, 79f, 30.4f);
}