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不支持多重继承)

  • 相关阅读:
    UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
    UVa 1658 (拆点法 最小费用流) Admiral
    UVa 11082 (网络流建模) Matrix Decompressing
    UVa 753 (二分图最大匹配) A Plug for UNIX
    UVa 1451 (数形结合 单调栈) Average
    UVa 1471 (LIS变形) Defense Lines
    UVa 11572 (滑动窗口) Unique Snowflakes
    UVa 1606 (极角排序) Amphiphilic Carbon Molecules
    UVa 11054 Wine trading in Gergovia
    UVa 140 (枚举排列) Bandwidth
  • 原文地址:https://www.cnblogs.com/doublesong/p/2614042.html
Copyright © 2011-2022 走看看