你的团队刚刚签下合同,负责建立Weather公司的下一代气象站——Internet气象站
建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计、天气预报。并提供一组API,让其他开发人员可以写出自己的气象布告板。
WeatherData {
getTemperature(); // 返回最近的气象测量数据:温度
getHumidity(); // 返回最近的气象测量数据:湿度
getPressure(); // 返回最近的气象测量数据:气压
measurementsChanged(); // 一旦气象测量更新,此方法会被调用
}
我们的工作是实现measurementsChanged(),好让它更新目前状况、气象统计、天气预报这三个布告板
public class WeatherData {
// 实例变量声明
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
currentConditionDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
// 其他的WeatherData方法
}
这样做的坏处有:
1. 我们是针对具体实现编程,而非针对接口编程
2. 对于每个新的布告板,我们都得修改代码
3. 我们无法再运行时动态地增加(或删除)布告板
4. 我们尚未封装改变的部分
在软件工程中,出版者改称为“主题”(Subject),订阅者改称为“观察者”(Observer)。
当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
观察者模式提供了一种对象设计,让主题和观察者之间松耦合
1. 主题只知道观察者实现了某个接口(Observer),而不需要知道具体实现类
2. 任何时候我们都可以增加新的观察者、运行时可以用新的观察者取代现有观察者、可以删除某些观察者
3. 当有新类型的观察者出现时,主题的代码无需改变
4. 可以独立地复用主题或观察者
5. 改变主体或者观察者的一方,并不会影响另一方
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
public interface Observer {
void update(float temp, float humidity, float pressure);
}
public interface DisplayElement {
void display();
}
java.util包内包含了最基本的Observer接口与Observable类,Observer接口与Observable类使用上更方便,因为许多功能都已经事先准备好了。你甚至可以使用推(push)或拉(pull)的方式传送数据。
setChanged() {
changed = true;
}
notifyObservers(Object arg) {
if(changed) {
for every observer on the list {
call update(this, arg)
}
changed = false
}
}
notifyObservers() {
notifyObservers(null)
}