1. 程式人生 > >HeadFirst 觀察者模式(observer)

HeadFirst 觀察者模式(observer)

使用目的

降低互動物件的耦合度

定義

觀察者模式:在物件之間定義一對多的依賴,這樣一來,當一個物件改變狀態,依賴它的物件都會收到通知,並自動更新。

1對多的關係 ,1 是被觀察者(主題),多是觀察者。觀察者通過訂閱主題,以便在主題資料發生變化時,收到更新。

生活中的例子

以報紙或雜誌的訂閱分析
1.報社的業務出版報紙。
2.訂閱某家報社的報紙後,只要報社出新報紙,就會給你送來,只要你是他的客戶,就會源源不斷收到新報紙。
3.當你不想看報紙的時候,只要取消訂閱,那就不會再收到新的報紙。
4.只要報社還在運營,就會不斷地有個人或單位訂閱或取消訂閱報紙。

通過圖的方式描述觀察者和被觀察者的關係:

這裡寫圖片描述

類圖關係

這裡寫圖片描述

實際應用

下面以氣象站天氣預報為例介紹觀察者模式具體使用
我們要實現一個從氣象站獲取資訊,實現目前狀況(溫度,溼度,氣壓)、氣象統計、天氣預報 三個功能的應用

類圖關係應該是這樣的:
這裡寫圖片描述

首先是主題與觀察者介面

public interface Subject {
    /**
     * 觀察者與被觀察者建立依賴關係
     * @param o
     */
    public void registerObserver(Observer o);
    /**
     * 取消觀察者與被觀察者的依賴關係
     * @param o
     */
public void removeObserver(Observer o); /** * 資料更新通知觀察者 */ public void notifyObservers(); }
public interface Observer {
    /**
     * 所有的氣象元件觀察者實現此介面,這樣當主題通知觀察者時,有了一個共同的介面
     * @param temp
     * @param humidity
     * @param pressure
     */
    void update(float temp,float
humidity,float pressure); }

接下來是具體的 Subject 氣象資料:

public class WeatherData implements Subject {

    private ArrayList observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData(){
        observers = new ArrayList();
    }
    /**
     * 將觀察者與自身建立依賴關係
     */
    public void registerObserver(Observer o) {
        // TODO Auto-generated method stub
        observers.add(o);
    }
    /**
     * 將觀察者與自身解除依賴關係
     */
    public void removeObserver(Observer o) {
        // TODO Auto-generated method stub
        int i = observers.indexOf(o);
        if(i >= 0){
            observers.remove(i);
        }
    }

    public void notifyObservers() {
        // TODO Auto-generated method stub
        for(int i = 0;i < observers.size(); i++){
            Observer observer = (Observer) observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }
    public void measurementsChanged(){
        notifyObservers();
    }
    /**
     * 取到最新的溫度 溼度 氣壓時,會發出測量資料改變,通知觀察者
     * @param temperature
     * @param humidity
     * @param pressure
     */
    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    //other method
}

舉例以當前狀況作為觀察者的具體實現

/**
 * 目前狀況 溫度 溼度 氣壓
 * @author admin
 *
 */
public class CurrentConditionsDisplay implements Observer,DisplayElement{
    private float temperature;
    private float humidity;
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData){

        this.weatherData = weatherData;
        //註冊依賴
        weatherData.registerObserver(this);
    }

    public void display() {
        // TODO Auto-generated method stub
        System.out.println("Current conditions:"+temperature +"F degrees and "+
                humidity+"% humidity");
    }
    /**
     * 接收到 Subject 發來的資料更新
     */
    public void update(float temp, float humidity, float pressure) {
        // TODO Auto-generated method stub
        this.temperature = temp;
        this.humidity = humidity;
        display();
    }
}
/**
 * 觀察者模式
 * @author admin
 *
 */
public class WeatherStation {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay conditionsDisplay =
                new CurrentConditionsDisplay(weatherData);
//      ForecastDisplay forecastDisplay =
//              new ForecastDisplay(weatherData);

        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);

    }

}
public interface DisplayElement {

    void display();

}

這樣,就實現了觀察者模式使用。

Java 本身實現了觀察者模式, 具體可以檢視import java.util.Observable;和import java.util.Observer;

PS

歡迎愛學習的小夥伴加群一起進步:230274309 。

一起分享,一起進步!少划水,多晒乾貨!!歡迎大家!!!(進群潛水者勿加)