zoukankan      html  css  js  c++  java
  • 观察者模式

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

    这个模式可以通过 报纸订阅服务的过程进行描述:

    当订阅者向出版商订阅了某一个杂志之后,只要这个出版商每月出了新的杂志,就会自动把杂志快递给已经向它订阅的用户。

    这里的出版商就相当于观察者模式中的“一”,称为主题(Subject),订阅者相当于观察者模式中的“多”,称为观察者(Observer)。

    订阅者想要收到每月的新杂志,就必须向出版商进行订阅。出版商只要有新的杂志出版 ,就自动将新的杂志送给订阅者。

    下面看一个例子:

    我们从气象站,取得天气数据对象 ,我们要把天气数据对象中的天气数据,发送给每个天气布告板。

    只要天气数据对象中天气数据一更新,就同步把天气数据更新到天气布告板。

    进行抽象 ,这里的天气数据对象就相当于主题,天气布告板就相当于观察者。

    类图:

    主题接口    Subject接口:

     1 /**
     2  * 这是 主题的接口类   Subject接口   
     3  * @author wly
     4  *
     5  */
     6 public interface Subject {
     7       /**
     8        * 向主题对象 ,注册一个传入的观察者对象  
     9        * @param observer
    10        */
    11       public  void  registerObserver(Observer  observer);    
    12       /**
    13        * 从主题对象已经注册的观察者集合中,移除传入的指定的观察者对象
    14        * @param observer
    15        */
    16       public  void  removerObserver(Observer observer);
    17       /**
    18        * 主题对象调用这个方法,发送消息,通知已经向它注册的观察者对象
    19        */
    20       public  void  notifyObservers();
    21 }

    观察者接口   Observer接口:

    /**
     * 这是观察者的接口   Observer接口 
     * @author wly
     *
     */
    public interface Observer {
          /**
           * 提供一个状态更新的接口 , 在主题对象的notifyObservers()方法中,被调用
           * @param temp     温度
           * @param humidity 湿度
           * @param pressure 气压
           */
          public  void   update(float temp , float humidity , float pressure);
    }

    具体的主题实现类   WeatherData类:

     1 /**
     2  * 这是具体的主题对象  WeatherData类   
     3  * @author wly
     4  *
     5  */
     6 public class WeatherData implements Subject {
     7     //声明一个list集合     用于存放向主题对象 注册的 观察者对象
     8     private  List<Observer>  observersList ;
     9     //温度变量
    10     private  float  temp;
    11     //湿度变量
    12     private  float  humidity;
    13     //气压变量 
    14     private  float  pressure;
    15     
    16     public  WeatherData()
    17     {
    18         this.observersList = new ArrayList<Observer>();
    19     }
    20     
    21     //注册观察者对象
    22     @Override
    23     public void registerObserver(Observer observer) {
    24         
    25         observersList.add(observer);
    26     }
    27     //移除观察者对象
    28     @Override
    29     public void removerObserver(Observer observer) {
    30          //放回observer对象在 observersList中的索引 ,如果存在返回索引值,不存在返回-1
    31          int  i = observersList.indexOf(observer);
    32          if(i >= 0)
    33          {
    34              observersList.remove(i);
    35          }
    36     }
    37     //通知已经注册了观察者对象  
    38     @Override
    39     public void notifyObservers() {
    40         for(int i = 0 ; i < observersList.size() ; i++)
    41         {
    42             Observer  observer  = observersList.get(i);
    43             observer.update(temp, humidity, pressure);
    44         }
    45     }
    46     //模拟测量值变化  ,变化之后通知已经注册了观察者对象
    47     public void  setMeasure(float  temp,float  humidity,float  pressure)
    48     {
    49         this.temp = temp;
    50         this.humidity = humidity;
    51         this.pressure = pressure;
    52         
    53         notifyObservers();
    54     }
    55 }

    具体的观察者实现类   布告板  CurrentConditionDisplay类:

     1 /**
     2  * 这是观察者对象   天气情况布告板   CurrentConditionDisplay类  
     3  * @author wly
     4  *
     5  */
     6 public class CurrentConditionDisplay implements Observer {
     7     private  float  temp;        //温度 
     8     private  float  humidity;    //湿度
     9     private  float  pressure;    //气压
    10     
    11     @Override
    12     public void update(float temp, float humidity, float pressure) {
    13          this.temp = temp;
    14          this.humidity = humidity;
    15          this.pressure = pressure;
    16     }
    17     
    18     //布告板的显示信息
    19     public  void  display()
    20     {
    21         System.out.println("当前天气情况如下:");
    22         System.out.println("温度:"+temp);
    23         System.out.println("湿度:"+humidity);
    24         System.out.println("气压:"+pressure);
    25     }
    26 }

    最后提供一个测试类:

     1 public class TestClass {
     2     
     3      public static void main(String[] args) {
     4            //创建两个观察者对象    布告板1 和 布告板2
     5            CurrentConditionDisplay  ccd1  = new  CurrentConditionDisplay();
     6            CurrentConditionDisplay  ccd2  = new  CurrentConditionDisplay();
     7            
     8            //创建一个主题对象   天气数据对象
     9            WeatherData  wd = new WeatherData();
    10            //将两个观察者对象布告板 向主题对象进行注册
    11            wd.registerObserver(ccd1);
    12            wd.registerObserver(ccd2);
    13            //模拟 天气数据变化
    14            wd.setMeasure(25.2F, 36.6F, 82.9F);
    15            
    16            //显示布告板的天气信息 
    17            ccd1.display();
    18            ccd2.display();
    19            
    20     }
    21 }

     运行结果如下:

    在JDK中内置类 一个Observerable类 和  Observer接口 。

    其中这里的Observerable类相当于我们所写的 Subject接口。  Observerable类已经提供了 注册,移除,通知等方法。

    我们在定义一个具体主题类时,直接继承Observerable类就可以继承那些方法,不需要自己写。

    Observer接口就相当于我们所写的 Observer接口,这个接口中只有一个update方法,供具体的观察者类去实现。

  • 相关阅读:
    python unittest一个简单的实例
    解决python编码格式错误问题
    一个简便的方法,获取某个页面元素的Xpath值
    Xpath基础语法学习
    postman发送带cookie的http请求
    postman测试接口之POST提交本地文件数据
    使用Jmeter录制web脚本
    mac 之 jmeter下载、解压、启动
    第三方测评公司的一些基础理念
    jmeter简单的压测案例——访问百度并发5,持续请求15
  • 原文地址:https://www.cnblogs.com/wangliyue/p/4178028.html
Copyright © 2011-2022 走看看