观察者模式解读

简介: 观察者模式解读

3abc25c9b191488ca23e0e39856dbf6b.png

问题引进

天气预报项目需求

1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。
2) 需要设计开放型 API,便于其他第三方也能接入气象站获取数据。
3) 提供温度、气压和湿度的接口
4) 测量数据更新时,要能实时的通知给第三方

天气预报设计方案 1-普通方案

1)通过getXxx方法。可以让第三方介入,并得到相关信息

2)当数据更新时,气象站通过调用dataChange()去更新数据,当数据更新时,就能得到最小消息,当然也可以通过推送的方式去。

CurrentConditions可以理解为我们的气象局网站

传统方式代码实现

CurrentConditions

1. public class CurrentConditions {
2. // 温度,气压,湿度
3. private float temperature;
4. private float pressure;
5. private float humidity;
6. //更新 天气情况,是由 WeatherData 来调用,我使用推送模式
7. public void update(float temperature, float pressure, float humidity) {
8. this.temperature = temperature;
9. this.pressure = pressure;
10. this.humidity = humidity;
11.         display();
12.     }
13. //显示
14. public void display() {
15.         System.out.println("***Today mTemperature: " + temperature + "***");
16.         System.out.println("***Today mPressure: " + pressure + "***");
17.         System.out.println("***Today mHumidity: " + humidity + "***");
18.     }
19. 
20. }

WeatherData

1. public class WeatherData {
2. private float temperatrue;
3. private float pressure;
4. private float humidity;
5. private CurrentConditions currentConditions;
6. //加入新的第三方
7. public WeatherData(CurrentConditions currentConditions) {
8. this.currentConditions = currentConditions;
9.     }
10. public float getTemperature() {
11. return temperatrue;
12.     }
13. public float getPressure() {
14. return pressure;
15.     }
16. public float getHumidity() {
17. return humidity;
18.     }
19. public void dataChange() {
20. //调用 接入方的 update
21.         currentConditions.update(getTemperature(), getPressure(), getHumidity());
22.     }
23. //当数据有更新时,就调用 setData
24. public void setData(float temperature, float pressure, float humidity) {
25. this.temperatrue = temperature;
26. this.pressure = pressure;
27. this.humidity = humidity;
28. //调用 dataChange, 将最新的信息 推送给 接入方 currentConditions
29.         dataChange();
30.     }
31. }

Client

1. public class Client {
2. public static void main(String[] args) {
3. //创建接入方 currentConditions
4. CurrentConditions currentConditions = new CurrentConditions();
5. //创建 WeatherData 并将 接入方 currentConditions 传递到 WeatherData 中
6. WeatherData weatherData = new WeatherData(currentConditions);
7. //更新天气情况
8.         weatherData.setData(30, 150, 40);
9. //天气情况变化
10.         System.out.println("============天气情况变化=============");
11.         weatherData.setData(40, 160, 20);
12.     }
13. }

问题分析

1) 其他第三方接入气象站获取数据的问题

2) 无法在运行时动态的添加第三方 (新浪网站)
3) 违反 ocp 原则=>观察者模式
//在 WeatherData 中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到 dataChange, 不利于维护,也不是动态加入
public void dataChange() {
currentConditions.update(getTemperature(), getPressure(), getHumidity());
}

观察者模式原理

1) 观察者模式类似订牛奶业务
2) 奶站/气象局:Subject
3) 用户/第三方网站:Observer
 Subject:登记注册、移除和通知
1) registerObserver 注册
2) removeObserver 移除
3) notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送,看具体需求定
 Observer:接收输入

观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方。用户时 Observer,是多的一方。

观察者模式解决天气预报需求

代码实现

Observer

1. public interface Observer {
2. public void update(float temperature, float pressure, float humidity);
3. }

Subject

1. public interface Subject {
2. public void registerObserver(Observer o);
3. public void removeObserver(Observer o);
4. public void notifyObservers();
5. }

CurrentConditions

1. public class CurrentConditions implements Observer{
2. // 温度,气压,湿度
3. private float temperature;
4. private float pressure;
5. private float humidity;
6. @Override
7. public void update(float temperature, float pressure, float humidity) {
8. this.temperature=temperature;
9. this.pressure=pressure;
10. this.humidity=humidity;
11.         display();
12.     }
13. public void display(){
14.         System.out.println("***Today mTemperature: " + temperature + "***");
15.         System.out.println("***Today mPressure: " + pressure + "***");
16.         System.out.println("***Today mHumidity: " + humidity + "***");
17.     }
18. }

BaiduSite  

1. public class BaiduSite implements Observer{
2. // 温度,气压,湿度
3. private float temperature;
4. private float pressure;
5. private float humidity;
6. @Override
7. public void update(float temperature, float pressure, float humidity) {
8. this.temperature=temperature;
9. this.pressure=pressure;
10. this.humidity=humidity;
11.         display();
12.     }
13. public void display(){
14.         System.out.println("***Today mTemperature: " + temperature + "***");
15.         System.out.println("***Today mPressure: " + pressure + "***");
16.         System.out.println("***Today mHumidity: " + humidity + "***");
17.     }
18. }

WeatherData  

1. public class WeatherData  implements  Subject{
2. private float temperature;
3. private float pressure;
4. private float humidity;
5. private ArrayList<Observer> observers;
6. 
7. public WeatherData() {
8.         observers = new ArrayList<Observer>();
9.     }
10. public float getTemperature() {
11. return temperature;
12.     }
13. public float getPressure() {
14. return pressure;
15.     }
16. public float getHumidity() {
17. return humidity;
18.     }
19. 
20. public void  setData(float temperature,float pressure,float humidity){
21. this.temperature = temperature;
22. this.pressure = pressure;
23. this.humidity = humidity;
24. //调用 dataChange, 将最新的信息 推送给 接入方 currentConditions
25.         notifyObservers();
26.     }
27. 
28. //添加一个观察者
29. @Override
30. public void registerObserver(Observer o) {
31.         observers.add(o);
32.     }
33. 
34. //移除一个观察者
35. @Override
36. public void removeObserver(Observer o) {
37. if(observers.contains(o)) {
38.             observers.remove(o);
39.         }
40.     }
41. 
42. @Override
43. public void notifyObservers() {
44. // TODO Auto-generated method stub
45. for(int i = 0; i < observers.size(); i++) {
46.             observers.get(i).update(this.temperature, this.pressure, this.humidity);
47.         }
48.     }
49. }

client  

1. public class client {
2. public static void main(String[] args) {
3. // TODO Auto-generated method stub
4. //创建一个 WeatherData
5. WeatherData weatherData = new WeatherData();
6. //创建观察者
7. CurrentConditions currentConditions = new CurrentConditions();
8. BaiduSite baiduSite = new BaiduSite();
9. //注册到 weatherData
10.         weatherData.registerObserver(currentConditions);
11.         weatherData.registerObserver(baiduSite);
12. //测试
13.         System.out.println("通知各个注册的观察者, 看看信息");
14.         weatherData.setData(10f, 100f, 30.3f);
15.         weatherData.removeObserver(currentConditions);
16. //测试
17.         System.out.println();
18.         System.out.println("通知各个注册的观察者, 看看信息");
19.         weatherData.setData(10f, 120f, 30.3f);
20. 
21.     }
22. }

 观察者模式的好处

1) 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。
2) 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码,遵守了 ocp 原则

目录
打赏
0
0
0
0
64
分享
相关文章
观察者模式
观察者模式是一种行为型设计模式,用于定义对象间的一对多依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会自动收到通知并更新。该模式主要用于实现发布-订阅机制。核心角色包括主题(Subject)、观察者(Observer)、具体主题(Concrete Subject)和具体观察者(Concrete Observer)。优点包括低耦合、动态添加观察者和自动更新,但也有可能引起过多更新、不适合同步通知和可能造成内存泄漏等缺点。适用于气象站数据更新、股票价格监控和用户界面组件更新等场景。
56 4
|
9月前
|
C++
【C++】—— 观察者模式
【C++】—— 观察者模式
【观察者模式】 ——每天一点小知识
【观察者模式】 ——每天一点小知识
5 # 观察者模式
5 # 观察者模式
44 0
我学会了,观察者模式
观察者模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
147 0
我学会了,观察者模式
深入剖析观察者模式
深入剖析观察者模式
170 0
观察者模式的实际应用
遇到一个用观察者模式解决问题的场景,和大家一起分享

热门文章

最新文章