观察者模式
传统方法:
/**
* @author 孙一鸣 on 2020/2/18
*
* 包含最新的天气信息
*/
public class WeatherData {
private float temperatrue;
private float pressure;
private float humidity;
private CurrentConditions currentConditions;
public WeatherData(CurrentConditions currentConditions) {
this.currentConditions = currentConditions;
}
public float getTemperature() {
return temperatrue;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
public void dataChange() {
//数据改变时,调用第三方的方法,通知第三方
currentConditions.update(getTemperature(), getPressure(), getHumidity());
}
//数据更新
public void setData(float temperature, float pressure, float humidity) {
this.temperatrue = temperature;
this.pressure = pressure;
this.humidity = humidity;
dataChange();
}
}
第三方使用数据网站
/**
* @author 孙一鸣 on 2020/2/18
*/
public class CurrentConditions {
//温度 气压 湿度
private float temperature;
private float pressure;
private float humidity;
//每次数据更新 数据WeatherData 将调用此方法 ,并将最新数据传入
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("***Today mTemperature: " + temperature + "***");
System.out.println("***Today mPressure: " + pressure + "***");
System.out.println("***Today mHumidity: " + humidity + "***");
}
}
测试:
/**
* @author 孙一鸣 on 2020/2/18
*/
public class Client {
public static void main(String[] args) {
CurrentConditions currentConditions = new CurrentConditions();
WeatherData weatherData = new WeatherData(currentConditions);
weatherData.setData(30, 150, 40);
}
}
分析:
如果此时,百度网站也想要获得天气数据,我们该怎么改呢?
1.创建观察数据者 百度网站
2.更改目标数据WeatherData
违反ocp原则,
//在WeatherData中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到dataChange, 不利于维护,也不是动态加入
public void dataChange() {
currentConditions.update(getTemperature(), getPressure(), getHumidity());
}
观察者模式:
观察者模式类似订牛奶业务
- 奶站/气象局:Subject
- 用户/第三方网站:Observer
Subject:登记注册、移除和通知
1) registerObserver 注册
2) removeObserver 移除
3) notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送,看具体需求定
Observer:接收输入
update()
观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化,比如这里的奶站是Subject,是1的一方。用户时Observer,是多的一方。
类图:
观察者模式结构中通常包括观察目标和观察者两个继承层次结构
目标: Subject 接口:
/**
* @author 孙一鸣 on 2020/2/18
* 接口,让WeatherData 来实现
*/
public interface Subject {
public void registerObserver(MyObserver o);
public void removeObserver(MyObserver o);
public void notifyObserver();
}
观察者: Observer 接口:
/**
* 观察者接口
* @author 孙一鸣 on 2020/2/18
*/
public interface MyObserver {
public void update(float temperature , float pressure ,float humidity);
}
观察者: Observer 实现 : 百度网站要获得天气信心 :
/**
* @author 孙一鸣 on 2020/2/18
*/
public class BaiDuCurrentConditions implements Observer {
//温度 气压 湿度
private float temperature;
private float pressure;
private float humidity;
//每次数据更新 数据WeatherData 将调用此方法 ,并将最新数据传入
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("***Today mTemperature: " + temperature + "***");
System.out.println("***Today mPressure: " + pressure + "***");
System.out.println("***Today mHumidity: " + humidity + "***");
}
}
目标: subject实现 : 气象中心发布信息:
/**
* @author 孙一鸣 on 2020/2/18
* <p>
* 包含最新的天气信息
* 使用ArrayList 管理观察者
* 当数据更新时 主动遍历ArrayList 通知观察者 更改最新信息
*/
public class WeatherData implements Subject {
private float temperature;
private float pressure;
private float humidity;
//private CurrentConditions currentConditions;
//观察者集合
private ArrayList<MyObserver> observers;
public WeatherData() {
observers = new ArrayList<>();
}
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
public void dataChange() {
notifyObserver();
}
//数据更新
public void setData(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
dataChange();
}
@Override
public void registerObserver(MyObserver o) {
observers.add(o);
}
@Override
public void removeObserver(MyObserver o) {
observers.remove(o);
}
@Override
public void notifyObserver() {
for (int i = 0; i <observers.size() ; i++) {
observers.get(i).update(this.temperature,this.pressure,this.humidity);
}
}
}
观察者模式测试:
/**
* @author 孙一鸣 on 2020/2/18
*/
public class Client {
public static void main(String[] args) {
//创建目标
WeatherData weatherData = new WeatherData();
//创建观察者
CurrentConditions currentConditions = new CurrentConditions();
//注册观察者
weatherData.registerObserver(currentConditions);
//测试
weatherData.setData(100, 100, 40);
}
}
观察者模式的好处
- 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除
和通知。 - 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核
心类WeatherData不会修改代码,遵守了ocp原则。