今天的需求是要实现一个天气预报系统,当然天气预报的数据不需要我们自己去观测和记录,已经有气象局完成了这个工作, 并且提供给我们一个类:
public class WeatherData {
private float getPressure() {
return 0;
}
private float getHumidity() {
return 0;
}
private float getTemperature() {
return 1;
}
public void measurementsChanged() {
//TODO 获得通知后,实现相应的内容
}
}
这个类中有提供,温度、湿度、气压的获取手段,并且当气象局采集到数据后,会调用measurementsChanged,这里我们不关心是怎么被调用到的,只要知道,当数据采集回来后,measurementsChanged方法会被调用。如果是你的话,你会怎么实现?
如果是我,我会在measurementsChanged方法里实现我的逻辑。
public class WeatherData {
private float getPressure() {
return 0;
}
private float getHumidity() {
return 0;
}
private float getTemperature() {
return 1;
}
public void measurementsChanged() {
currentConditionsDisplay.update(getHumidity(), getTemperature(), getPressure());
forcastDisplay.update(getHumidity(), getTemperature(), getPressure());
statisticDisplay.update(getHumidity(), getTemperature(), getPressure());
}
}
可是这样实现的问题在于,如果有更多的公司接入天气预报系统,measurementsChanged方法就要极度膨胀,一直不断的被改写。根据设计模式的原则:针对接口编程 和 把变化的部分剥离出来,我们需要对measurementsChanged方法进行整改,使其适合作为公共API对外提供服务。
那么我们来分析一下我们的需求:
- 我们需要在气象局获得数据的时候通知到我们
- 能够灵活动态的增加和删除被通知对象,不必每次增加或删除被通知者时都要改写WeatherData代码。
结合第一版的实现逻辑,我们很容易的能想到,可以设计一个更新动作的接口,所有实现类都实现这个接口那么,我们就可以把measurementsChanged方法简化成一行。
public class WeatherData {
public Observer observer;
public void measurementsChanged() {
observer.update(getHumidity(), getTemperature(), getPressure());
}
}
其次,我们要能够动态的增加和删除被通知者,所以我们需要持有(has a)通知对象,在需要通知的时候遍历就可以了。我们还要增加添加和删除被通知者的方法,用来动态的管理被通知对象。
public class WeatherData {
public List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void delObserver(Observer observer) {
observers.remove(observer);
}
public void notifierObservers() {
for(Observer o:observers) {
o.update(getHumidity(), getTemperature(), getPressure());
}
}
public void measurementsChanged() {
notifierObservers();
}
}
作为被观察者,我们需要持有WeatherData对象,才能把”自己“添加到WeatherData或者从WeatherData删除。
public class ForcastObserver implements Observer {
public float temperature;
public float humidity;
public float pressure;
public WeatherData weatherData;
public ForcastObserver (WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.addObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println(temperature + humidity + pressure);
}
}
测试代码如下:
public class TestForcastObserver {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
ForcastObserver forcastObserver = new ForcastObserver(weatherData);
weatherData.measurementsChanged();
}
}