设计模式思考之观察者模式

观察者模式的定义:

观察者模式定义了对象的一对多依赖,这样一来,让一个对象改变状态时,它的所有依赖者都会收到通知并且会自动更新。

观察者模式的实例:

实例:建立一个气象站应用,利用WeatherData对象取得数据,并更新三个布告板:当前状况、气象统计和天气预报,当WeatherObject对象获得最新的测量数据时,三种布告板必须实时更新。

其实观察者模式可以从订报的角度来理解。
拿报纸的订阅来举例子:

  1. 报社的业务就是出版报纸
  2. 向某家报社订阅了报纸,只要他们有心得报纸出版,就会给你 送过来。只要你是他们的订户,你就会一直收到新报纸。
  3. 当你不再看报纸的时候,取消订阅,他们就不会再送报纸过来
  4. 只要报社还在运营,就会一直有人向他们订阅报纸或者取消订阅报纸。

定义观察者模式,类图

观察者模式类图.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

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

你可能感兴趣的:(设计模式思考之观察者模式)