设计模式思考之观察者模式
观察者模式的定义:
观察者模式定义了对象的一对多依赖,这样一来,让一个对象改变状态时,它的所有依赖者都会收到通知并且会自动更新。
观察者模式的实例:
实例:建立一个气象站应用,利用WeatherData对象取得数据,并更新三个布告板:当前状况、气象统计和天气预报,当WeatherObject对象获得最新的测量数据时,三种布告板必须实时更新。
其实观察者模式可以从订报的角度来理解。
拿报纸的订阅来举例子:
- 报社的业务就是出版报纸
- 向某家报社订阅了报纸,只要他们有心得报纸出版,就会给你 送过来。只要你是他们的订户,你就会一直收到新报纸。
- 当你不再看报纸的时候,取消订阅,他们就不会再送报纸过来
- 只要报社还在运营,就会一直有人向他们订阅报纸或者取消订阅报纸。
定义观察者模式,类图
观察者模式类图.png任何时候我们都可以增加新的观察者,因为主题唯一依赖的东西是一个实现了Observer接口的对象列表。所以我们可以随时增加观察者。事实上,在运行时我们可以用新的观察者取代现有的观察者,主题不会受到任何影响。同样的也可以在任何时候删除某些观察者。
有新类型的观察者出现时,主题的代码不需要修改。加入我们有个新的具体类需要当观察者,我们不需要为了兼容新类型而修改主题的代码,所有要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。主题不在乎别的,它只会发送通知给所有实现了观察者接口的对象。
这里体现了我们的一个设计原则,即为了交互对象之间的松耦合设计而努力。
松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的相互依赖降到了最低。
基于以上的原则,我们可以得出我们对于该气象站的设计图:
气象站设计图.png下面我们用代码来实现气象站
让我们从建立接口开始
Public interface Subject{
//这两个方法都需要一个观察者作为变量,该观察者是用来注册或者被删除的
Public void registerObserver(Observer o);
Public void removeObserver(Observer o);
//当主题状态改变时,这个方法会被调用,以通知所有的观察者
Public void notifyObservers();
}
Public interface Observer{
//当气象观测值改变时,主题会把这些状态值当做方法的参数,传递给观察者。
Public void update(float temp,float humidity,float pressure);
}
Public interface DisplayElement{
//当布告板需要显示时,调用此方法。
Public void display();
}
在WeatherData中实现接口
Public class WeatherData implements Subject{
Private ArrayList observers;
Private float temperature;
Private float humidity;
Private float pressure;
}
Public WeatherData(){
Ovservers=new ArrayList();
}
Public void registreObserver(Observer o){
Observers.add(o);
}
Public void removeObserver(Observer o){
int i=observers.indexOf(o);
If(i>=0){
Observers.remove(i);
}
}
Public void notifyObservers(){
for(int i=0;i<observers.size();i++){
Observer observer =(Observer) observers.get(i);
Observer.update(temperature,humidity,pressure);
}
}
Public void messurementsChanged(){
notifyObservers();
}
Public void setMeasurements(float temperature,float humidity,float pressure) {
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
}
//WeatherData的其他方法
}
现在让我们来建立布告板
Public class CurrentConditionsDisplay implements Observer ,DisplayElement {
Private float temperature;
Private float humidity;
Private Subject weatherData;
//构造器需要weatherData对象作为注册之用
Public CurrentConditionsDisplay(Subjecy weatherData){
this.weatherData =weatherData;
weatherData.registerObserver(this);
}
Public void update(float temperature,float humidity,float pressure) {
this.temperature=temperature;
this.humidity=humidity;
Display();
}
Public void display(){
System.out.println(“Current conditions: “+temperature +”℃ and ” +humidity+ “% humidity”)
}
}
最后我们可以建立一个测试程序
Public class WeatherStation {
Public static void main(String[] args) {
WeatherData weatherData=new WeatherData();
CurrentConditionsDisplay currentDisplay =new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(24,65,30.4f);
weatherData.setMeasurements(25,64,29.4f);
weatherData.setMeasurements(29,59,28.4f);
}
}
运行程序,即可看到输出结果
Current conditions: 24 ℃ and 65.0 % humidity
Current conditions: 25 ℃ and 64.0 % humidity
Current conditions: 29 ℃ and 59.0 % humidity
这样一个观察者模式的实例就完成了
java还有内置的观察者模式,Java API内有内置的观察者模式,java.util包内包含最基本的Observer接口与Observeable类,这和我们的Subject接口和 Observer接口很相似。
用我们的这个气象站的实现作比较,用java内置的观察者模式是有一点小的差异的,最明显的差异是WeatherData(也就是我们的主题)现在要扩展字Observable类,并继承一些添加、删除、通知观察者的方法。
下面是收集的一些比较好的有关于观察者模式的博文
1.观察者模式和Spring的结合 https://blog.csdn.net/zlts000/article/details/53462181?ref=myread
2.观察者模式与事件监听机制 https://blog.csdn.net/qq_22873427/article/details/77169781
3.设计模式--观察者模式的思考 https://mrdear.cn/2018/04/20/experience/design_patterns--observer/
4.设计模式 之 观察者 和监听器的区别 https://blog.csdn.net/xiaoliuliu2050/article/details/73274985
5观察者模式和Spring的结合 https://blog.csdn.net/zlts000/article/details/53462181?ref=myread
6.深入理解Javascript中的观察者模式 https://www.jb51.net/article/106119.htm
作者:lhsjohn