zoukankan      html  css  js  c++  java
  • 设计模式第二集——观察者模式(Observer)

      观察者模式,就像订报纸杂志。出版社(主题Subject)有新的报纸出版就会通知读者(观察者 Observer),当读者不想看报纸的时候,取消订阅就不会再受到新送来的报纸。这就是一种典型的观察者模式。

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

      观察者类图:

      Subject是主题接口,对象使用这个接口注册为观察者也可以把自己从观察者中删除。ConcreteSubject是实现主题的接口,除了注册和撤销方法之外还有notifyOvservers(),用于在状态改变是更新当前所有的观察者。

      Observer观察者接口,这个接口只有update()一个方法,当主题状态改变时它被调用。

    观察者模式提供了一种对象设计,让主题和观察者之间松耦合。对于主题和观察者之间唯一依赖的东西就是实现Observer接口的对象列表,可以随时增删观察者。

      举个例子:气象观测版。一个WeatherData对象有关于温度、湿度、气压等方面的信息,将信息发送给布告板,布告板有很多种。下面就是这个例子的类图,为布告板建立一个共同的接口。

    代码:

    首先建立三个接口:

     1 package com.Subject;
     2 
     3 import com.Observer.Observer;
     4 
     5 public interface Subject {
     6     public void registerObserver(Observer o);
     7     public void removeObserver(Observer o);
     8     //当主题状态改变时,这个方法会被调用,以通知所有的观察者
     9     public void notifyObservers();
    10 
    11 }
    12 
    13 package com.Observer;
    14 
    15 public interface Observer {
    16     //所有的观察者都需要实现update的方法
    17     //当气象观测值发生改变的时候,主题会把这些值作为参数传给观察者
    18     public void update(float temp,float humidity,float pressure);
    19 }
    20 
    21 package com.Display;
    22 
    23 public interface DisplayElement {
    24     //DisplayElement接口只包含一个display方法。当广告版需要显示时调用此方法
    25     public void display();
    26 
    27 }

    WeatherData实现主题的接口

     1 package com.Subject;
     2 
     3 import java.util.ArrayList;
     4 
     5 import com.Observer.Observer;
     6 
     7 public class WeatherData implements Subject{
     8     private ArrayList observers;//这个就是观察者的列表
     9     private float temperature;
    10     private float humidity;
    11     private float pressure;
    12     
    13     public WeatherData(){
    14         observers=new ArrayList();//观察者的list在构造函数中建立
    15     }
    16     
    17     public void registerObserver(Observer o) {
    18         observers.add(o);//注册就是把观察者加到列表中
    19         
    20     }
    21     
    22     public void removeObserver(Observer o) {
    23         int i=observers.indexOf(o);
    24         if(i>=0){
    25             observers.remove(i);
    26         }        
    27     }
    28 
    29     @Override
    30     public void notifyObservers() {
    31         //把状态告诉每一个观察者去更新数据
    32         for(int i=0;i<observers.size();i++){
    33             Observer observer=(Observer) observers.get(i);
    34             observer.update(temperature, humidity, pressure);
    35         }        
    36     }
    37     
    38     public void measurementsChanged(){
    39         //当从外界比如气象站得到更新观测值是,通知观察者
    40         notifyObservers();
    41     }
    42     public void setMeasurements(float temperature,float humidity,float pressure){
    43         this.humidity=humidity;
    44         this.pressure=pressure;
    45         this.temperature=temperature;
    46         measurementsChanged();
    47     }
    48 }

    布告板:

     1 package com.Display;
     2 
     3 import com.Observer.Observer;
     4 import com.Subject.Subject;
     5 
     6 public class CurrentConditionsDisplay implements Observer,DisplayElement{
     7     private float temperature;
     8     private float humidity;
     9     private Subject weatherData;
    10     
    11     
    12     public CurrentConditionsDisplay(Subject weatherData) {
    13         //在构造器时注册observer
    14         this.weatherData = weatherData;
    15         weatherData.registerObserver(this);
    16     }
    17 
    18     @Override
    19     public void display() {
    20         System.out.println("Current conditions:"+temperature+"F degree and"+humidity+"% humidity");
    21         
    22     }
    23 
    24     @Override
    25     public void update(float temp, float humidity, float pressure) {
    26         this.temperature=temp;
    27         this.humidity=humidity;
    28         display();        
    29     }
    30 
    31 }

    测试:

    package com.test;
    
    import com.Display.CurrentConditionsDisplay;
    import com.Subject.WeatherData;
    
    public class WeatherStation {
        public static void main(String args[]){
            //首先建立一个WeahterData对象(主题)
            WeatherData weatherdata=new WeatherData();
            //一个现实版
            CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherdata);
            //调用setMeasurements方法设立现在的weather值
            weatherdata.setMeasurements(80, 65, 30.4f);
        }
    
    }

    这样一个观察者模式,就做好了!

    需要注意的是,在java.util包中包含了Observer包,然后任何observable对象的addOvserver()方法,不想当观察者时,调用deleteObserver()方法就可以了。但是最好自己写观察者,因为java API的Observable是一个类,必须要设计一个类继承它。如果某个类想同时具有Observable类和另一个超类的行为,就没有办法了(因为java不支持多重继承)

  • 相关阅读:
    Isolation Forest原理总结
    python 黑客书籍 ——扫描+暴力破解
    DNS解析过程
    DNS污染——domain name的解析被劫持了返回无效的ip
    leetcode 427. Construct Quad Tree
    todo
    leetcode 172. Factorial Trailing Zeroes
    leetcode 26. Remove Duplicates from Sorted Array
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(3月3日)
    北京Uber优步司机奖励政策(3月2日)
  • 原文地址:https://www.cnblogs.com/doublesong/p/2614042.html
Copyright © 2011-2022 走看看