head first 设计模式之----Observer pattern (一)

2014-11-24 10:21:34 · 作者: · 浏览: 1

浅谈设计模式之----观察者模式

观察者模式也是我们日常程序编写中碰到比较多的一种设计模式。首先,所谓观察者模式定义就是指:在对象之间定义了一对多的依赖,这样一来,当一个对象的状态发生变化的时候,依赖它的多个对象都会收到通知并且自动更新。
平时的运用中,我们一般用到Observer pattern的实现方式主要是:自定义主题(Subject)和Observer(观察者)和JDK自己封装的java.util.Observer和java.util.Observable(类似subject)来实现的。在这里,我主要讲述自定义的Observer pattern的实现吧。

以下以气象预报站(WeatherStation)进行天气的预报为例子。气象站的需求是建立三块公布版,一块是当前气象预报(CurrentConditionDisplay)公布版、静态预报(StatisticDisplay)公布版、预报(ForeCastDisplay)公布版。其中主题的实现是气象站的数据提供(WeatherData)实现Subject(主题),观察者为Observer和DisplayElement两个接口。其中观察者的实现有三个,分别对应三块公布版。CurrentConditionDisplay、StatisticDisplay、ForestCastDisplay,散者均需要实现Observer和DisplayElement三个接口。从而,主题的实现类WeatherData通过调用观察者的接口通知观察者及时更新,观察者通过主题接口来向主题注册,在设计的过程中,会变的只是主题的状态和观察者的数目和类型。此模式可以改变依赖主题状态的对象而不该变主题的状态。
以下是代码的实现

package com.clark.observerpattern.subject;

import com.clark.observerpattern.observer.Observer;

/**
 * 气象站主题,其对应着多个Observer对象
 * @author Administrator
 *
 */
public interface Subject {
    //注册一个Observer
    public void registerObserver(Observer obj);
    //remove一个Observer
    public void removeObserver(Observer obj);
    //当主题对象发生改变的时候,通知所有的Observer
    public void notifyAllObserver();
}

package com.clark.observerpattern.observer;
/**
 * defination much observer object
 * @author Administrator
 *
 */
public interface Observer {
    //defined a update method,parameter include temp,humidity,pressure
    public void update(float temp,float humidity,float pressure);
}
package com.clark.observerpattern.observer;
/**
 * display 布告板的信息
 * @author Administrator
 *
 */
public interface DisplayElement {
    void display();
}

package com.clark.observerpattern;

import com.clark.observerpattern.observer.DisplayElement;
import com.clark.observerpattern.observer.Observer;
import com.clark.observerpattern.subject.Subject;

class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temp;
    private float humidity;
    private Subject weatherData;
    @Override
    public void display() {
        System.out.println("current conditions:"+temp+" F degrees and "+humidity+"% humidity");
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temp=temp;
        this.humidity=humidity;
        display();
    }
    public CurrentConditionsDisplay(Subject weatherData){
        this.weatherData=weatherData;
        //注册改Observer,从而在后面移除的时候方便关联
        weatherData.registerObserver(this);
    }
}
package com.clark.observerpattern.observer;
import java.util.*;

import com.clark.observerpattern.subject.Subject;
import com.clark.observerpattern.subject.WeatherData;
/**
 * 统计布告板
 * @author Administrator
 *
 */
public class StatisticsDisplay implements Observer, DisplayElement {
    private float maxTemp = 0.0f;
    private float minTemp = 200;
    private float tempSum= 0.0f;
    private int numReadings;
    private Subject weatherData;

    public StatisticsDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    public void update(float temp, float humidity, float pressure) {
        tempSum += temp;
        numReadings++;

        if (temp > maxTemp) {
            maxTemp = temp;
        }
 
        if (temp < minTemp) {
            minTemp = temp;
        }

        display();
    }

    public void display() {
        System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
            + "/" + maxTemp + "/" + minTemp);
    }
}

package com.clark.observerpattern.observer;

import com.clark.observerpattern.subject.Subject;
import com.clark.observerpattern.subject.WeatherData;

/**
 * 天气预报布告板的现场预报板块
 * @author Administrator
 *
 */
public class ForecastDisplay implements DisplayElement, Observer {
    private float currentPressure = 29.92f;  
    private float lastPressure;
    private Subject weatherData;
    
    public ForecastDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    public void update(float temp, float humidity, float pressure) {
        lastPressure = currentPressure;
        currentPressure = pressure;
        display();
    }

    public void display() {
        System.out.print("Forecast: ");
        if (currentPressure > lastPressure) {
            System.out.println("Improving weather on the way!");
        } e