天气预报需求
一个天气预报的项目,需求如下:
- 气象站可以每天测量到温度、湿度、气压等等以公告的形式发布出去
- 需要设计开放性API,便于第三方也能接入气象站获取数据
- 提供温度、气压、湿度的接口
- 测量数据更新时,能够实时通知给第三方
传统方案
- 初步设计一个WeatherData类,包含getTemperature、getHumidity、getPressure、dataUpdate四个方法
- 通过getXXX来获取不同信息,气象站通过调用dataUpdate来更新数据,当第三方再次获取就能得到最新数据,或者主动给第三方推送
/***
* @author shaofan
* @Description 传统方案解决天气预报需求
*/
public class WeatherForecast {
public static void main(String[] args) {
WeatherCondition weatherCondition = new WeatherCondition();
WeatherData weatherData = new WeatherData(weatherCondition);
weatherData.setData(1,1,1);
System.out.println(weatherCondition);
weatherData.setData(2,2,2);
System.out.println(weatherCondition);
}
}
/***
* 第三方天气信息
*/
class WeatherCondition{
private float temperature;
private float pressure;
private float humidity;
public void update(WeatherData weatherData){
this.temperature = weatherData.getTemperature();
this.pressure = weatherData.getPressure();
this.humidity = weatherData.getHumidity();
}
@Override
public String toString() {
return "WeatherCondition{" +
"temperature=" + temperature +
", pressure=" + pressure +
", humidity=" + humidity +
'}';
}
}
/***
* 气象站天气信息
*/
class WeatherData{
private float temperature;
private float pressure;
private float humidity;
private WeatherCondition weatherCondition;
public WeatherData(WeatherCondition weatherCondition){
this.weatherCondition = weatherCondition;
}
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
/**
* 气象站更新第三方的天气
*/
private void weatherUpdate(){
weatherCondition.update(this);
}
/**
* 气象站检测到天气更新
* @param temperature
* @param pressure
* @param humidity
*/
public void setData(float temperature,float pressure,float humidity){
this.temperature =temperature;
this.pressure = pressure;
this.humidity = humidity;
weatherUpdate();
}
}
问题分析
新增一个第三方,都需要创建一个新的第三方对象,并加入都dataChange中,不利于维护,也不是动态加入
观察者模式
- 被订阅方看作一个Subject,可以在这个Subject上面注册Observer观察者,Subject维护registerObserver、removeObserver、notifyObservers方法
- 观察者模式是对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化;Subject是1的一方、Observer是多的一方
观察者模式解决天气预报问题
/***
* @author shaofan
* @Description 观察者模式解决天气预报问题
*/
public class WeatherForecast {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
WeatherCondition weatherCondition = new WeatherCondition();
weatherData.registerObserver(weatherCondition);
weatherData.setData(1,1,1);
System.out.println(weatherCondition);
}
}
/***
* 被订阅方
*/
interface Subject{
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
/***
* 观察者
*/
interface Observer{
void update(WeatherData weatherData);
}
class WeatherData implements Subject{
private float temperature;
private float pressure;
private float humidity;
private List<Observer> observers;
public WeatherData(){
observers = new ArrayList<>();
}
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
@Override
public void registerObserver(Observer observer) {
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
this.observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : this.observers) {
observer.update(this);
}
}
public void setData(float temperature,float pressure,float humidity){
this.temperature =temperature;
this.pressure = pressure;
this.humidity = humidity;
notifyObservers();
}
}
class WeatherCondition implements Observer{
private float temperature;
private float pressure;
private float humidity;
@Override
public void update(WeatherData weatherData) {
this.temperature = weatherData.getTemperature();
this.pressure = weatherData.getPressure();
this.humidity = weatherData.getHumidity();
}
@Override
public String toString() {
return "WeatherCondition{" +
"temperature=" + temperature +
", pressure=" + pressure +
", humidity=" + humidity +
'}';
}
}
源码分析
jdk中Observeable类,使用了观察者模式
- Observable的作用等价于Subject,这里没有Subject抽象
- Observable已经实现了核心的方法,即管理Observer的方法
- Observer的地位和常规写法的Observer相同