设计模式-观察者模式
简单描述:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。例如:up主和订阅者之间的关系,当up主有视频更新时,就会将更新通知给订阅者。
所属类型:行为型模式
适用情况:目标对象状态发生改变,所有观察者对象都得到通知,进行广播通知。
关键代码:需要一个列表用来存储观察者们
除了上述所说的up主和订阅者之间的关系之外,还可以通过气候信息改变情况举个栗子。每当气候发生改变的时候,气象站就会收到通知,并且将通知的结果通知给每一个关注气象站公众号的用户,所以下面用代码来实现这个例子。
首先需要创建气象站这个管理信息的功能,在这里创建一个Subject
接口类型。
package observer; public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
气象站能够对用户
也就是所谓的观察者
进行注册,移除以及通知用户的操作,所以定义了相关的方法。
接着就来创建Observer
类,也就是所谓的观察者们
。
package observer; public interface Observer { public void update(float temp, float humidity, float pressure); }
顾名思义,观察者们的功能就只有接收对应的消息并且更新,所以仅定义updata
一个方法就够了。
接着,通过创建一个DisplayElement
接口来将对应的更新结果展示出来。
package observer; public interface DisplayElement { public void display(); }
接口定义完成,接下来的具体的实现了。首先是对应的天气的数据
,这里定义一个WeatherData
类用来存储天气的信息,并且实现对应的注册观察者,移除观察者以及通知观察者的功能。
package observer; import java.util.ArrayList; public class WeatherData implements Subject { private ArrayList observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if (i >= 0) { observers.remove(i); } } @Override public void notifyObservers() { for (int i = 0; i < observers.size(); i++) { Observer observer = (Observer) observers.get(i); observer.update(temperature, humidity, pressure); } } public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; notifyObservers(); } }
在这个WeatherData
类中,首先它的实例化需要新建一个列表用来存储观察者们,好在后面对这些观察者进行消息的通知。每当注册一个观察者registerObserver
紧接着就来完成数据的展示功能,这里创建一个CurrentConditionDisplay
类来将对应的数据展示出来,方便查看。
package observer; public class CurrentConditionDisplay implements Observer, DisplayElement { private float temperature; private float humidity; private float pressure; private Subject weatherData; public CurrentConditionDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void display() { System.out.println("temp: " + temperature + "\nhumidity: " + humidity + "\npressure: " + pressure); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; this.pressure = pressure; display(); } }
首先需要创建温度,湿度以及压强三个属性来存储获取到的天气信息。这个气候展示的功能首先需要实现Observer
接口的updata
方法,来将数据传入并且调用DisplayElement
接口的display
方法来进行展示。
最后通过创建一个WeatherState
类来进行调用查看结果。
package observer; public class WeatherState { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData); weatherData.setMeasurements(11, 11, 11); weatherData.setMeasurements(22, 22, 22); weatherData.setMeasurements(33, 33, 33); } }
运行结果如下所示:
temp: 11.0 humidity: 11.0 pressure: 11.0 temp: 22.0 humidity: 22.0 pressure: 22.0 temp: 33.0 humidity: 33.0 pressure: 33.0
发现每当调用一次setMeasurements
方法就会将对应的数据进行输出。
同样,在Java中有内置的观察者模式,也就是Observer
和Observable
这两个类。对照着刚才的例子,可以将Observer
与Observer
进行对照,其中的方法也就只有一个updata
类,Observable
可以和Subject
进行对照,两者的差距不是特别大,比较明显的是在这里的Subject
写的比较简单,而Observable
比较好用的是setChanged
方法,这个方法能够有选择的给观察者们进行信息的传递,也让程序更加具有弹性。
但是!!!!!!!!!
在Java9的时候,Observer和Observable就已经废除了。在网上查询了一下废除的原因,主要有以下三个原因:
1、不能序列化
Observable没有实现Serializable接口,它的内部成员变量都是私有的。子类不能通过继承它来对Observable的成员变量处理,所以子类也不能序列化。
2、不是线程安全
在java.util.Observalble文档里没有强制要求Observable是线程安全的,它允许子类覆盖重写Observable的方法,事件通知无序以及事件通知发生在不同的线程里,这些都是会影响线程安全的问题。
3、支持事件模型的功能简单
支持事件模型的功能很简单,例如,只是支持事情发生变化的概念,但不能提供更多哪些内容发生了改变
解决方法:
利用java.beans里面的PropertyChangeEvent和PropertyChangeListener来代替Observer和Observable。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!