观察者模式解读

简介: 观察者模式解读

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

相关文章
|
14天前
观察者模式
​ 如有错误或有补充,以及任何的改进意见,请在评论区留下您的高见,同时文中给出大部分示例 如果觉得本文写的不错,不妨点个赞,收藏一下,助力博主产生质量更高的作品 概念 观察者模式是一种对象行为型模式,它定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 在观察者模式中,存在两种类型的对象:目标对象和观察者对象。目标对象负责发出通知,而观察者对象则订阅目标对象,以便在目标对象的状态发生变化时接收到通知。一旦接收到通知,观察者对象就会执行相应的行为。 优缺点 观察者模式的优点主要包括: 解耦:观察者模式有助于降低目标对象和观察者对象
16 0
|
2月前
|
C++
【C++】—— 观察者模式
【C++】—— 观察者模式
|
2月前
|
设计模式 JavaScript 开发者
详细讲解什么是观察者模式
详细讲解什么是观察者模式
|
5月前
行为型 观察者模式(发布订阅)
行为型 观察者模式(发布订阅)
17 0
|
5月前
|
设计模式 Java
【观察者模式】 ——每天一点小知识
【观察者模式】 ——每天一点小知识
|
7月前
5 # 观察者模式
5 # 观察者模式
16 0
|
12月前
|
XML 设计模式 Java
观察者模式(下)
观察者模式(下)
42 0
|
12月前
|
设计模式
观察者模式(上)
观察者模式(上)
55 0
|
设计模式
我学会了,观察者模式
观察者模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
106 0
我学会了,观察者模式
|
存储
深入剖析观察者模式
深入剖析观察者模式
125 0