观察者模式解读

简介: 观察者模式解读

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 原则

相关文章
|
9月前
|
人工智能 小程序 程序员
我的 2024 年终总结,持续尝试
复盘一下今年做过的所有关于探索收入多样性的事情。包括这一年工作以外的 “工作进展”,收获的事项,遇到的种种问题,以及来年的计划等,最后希望能对大家有一点点参考意义。
166 2
|
10月前
|
传感器 机器学习/深度学习 人工智能
自动驾驶汽车中的AI:从概念到现实
【10月更文挑战第31天】自动驾驶汽车曾是科幻概念,如今正逐步成为现实。本文探讨了自动驾驶汽车的发展历程,从早期的机械控制到现代的AI技术应用,包括传感器融合、计算机视觉、路径规划和决策控制等方面。尽管面临安全性和法规挑战,自动驾驶汽车在商用运输、公共交通和乘用车领域展现出巨大潜力,未来将为人类带来更安全、便捷、环保的出行方式。
|
7月前
|
算法 数据安全/隐私保护
通过MATLAB实现PID控制器,积分分离控制器以及滑模控制器
本课题通过MATLAB实现PID控制器、积分分离控制器和滑模控制器,对比结果显示滑模控制具有最快的收敛性能、较强的鲁棒性和较小的超调量,优于其他两种控制器。系统仿真结果无水印,核心程序基于MATLAB 2022a。PID控制器由P、I、D单元组成,积分分离PI在大误差时不进行积分,减少超调;滑模控制通过设计滑动面使系统快速收敛,抑制扰动。
|
机器学习/深度学习 数据挖掘 开发者
|
开发者
🔥揭秘JSF导航:如何轻松驾驭页面跳转与流程控制?🎯
【8月更文挑战第31天】在 JavaServer Faces(JSF)中,导航规则是控制页面跳转和流程的关键。本文详细介绍 JSF 的导航规则,包括转发和重定向等跳转方式,并通过 `faces-config.xml` 文件配置示例展示如何实现不同场景下的页面跳转及流程控制,帮助开发者有效管理应用程序的页面流和用户交互,提升应用质量。
140 0
|
12月前
|
缓存 前端开发
React中函数式Hooks之memo、useCallback的使用以及useMemo、useCallback的区别
React中的`memo`是高阶组件,类似于类组件的`PureComponent`,用于避免不必要的渲染。`useCallback` Hook 用于缓存函数,避免在每次渲染时都创建新的函数实例。`memo`可以接收一个比较函数作为第二个参数,以确定是否需要重新渲染组件。`useMemo`用于缓存计算结果,避免重复计算。两者都可以用来优化性能,但适用场景不同:`memo`用于组件,`useMemo`和`useCallback`用于值和函数的缓存。
407 1
|
Java 程序员 网络安全
Flink处理函数实战之三:KeyedProcessFunction类
通过实战学习和了解处理函数的KeyedProcessFunction类
804 0
Flink处理函数实战之三:KeyedProcessFunction类
el-cascader组件实现点击、递归勾选联动子集children所有选项被选中。
el-cascader组件实现点击、递归勾选联动子集children所有选项被选中。