1. 程式人生 > >觀察者模式(Observer Pattern)

觀察者模式(Observer Pattern)


是什麼?

怎麼用?

什麼情況下用?

例項!


 

 

觀察者模式:

  一個目標物件管理所有依賴於它的觀察者物件,並且當它本身的狀態改變時主動發出通知。

  這時候就有問題了,目標怎麼知道誰是觀察者?誰不是觀察者?而且目標要怎麼通知觀察者?

  (個人感覺兩個類通訊就能用到這東西)

 

使用場景:

  今日頭條文章釋出後需要一系列的後續處理流程,比如更新這個作者建立的文章總數、將這篇文章推薦到對應的頻道、劃分文章的欄目、上報到推薦系統等等。那要其他的這些要怎麼知道文章是否釋出呢?這時候就可以用到觀察者模式了(事件機制)!

 

原理:

  目標類需要:

    1、註冊觀察者(觀察者通知目標:我要當你的觀察者)

    2、移除觀察者(觀察者通知目標:我要溜了)

    3、呼叫觀察者的提供的方法通知觀察者

  觀察者需要:

    1、提供目標通知觀察者時用到的方法

    2、在建構函式中呼叫目標的註冊方法將自己註冊成目標的觀察者

 

例子:

  氣象檢測例子:

    如圖,氣象站是獲取實際氣象資料的物理裝置,WeatherData物件是用來追蹤氣象站的資料,並更新佈告板。

    擴充WeatherData物件,使得佈告板能夠及時更新,並利於以後的擴充套件。

    

 

  Subject 是抽象目標,所有的目標都繼承這個抽象類,這個抽象類提供了三個最基本的註冊、移除、通知觀察者的方法!

  WeatherData 是具體目標,繼承自抽象目標Subject,這個類的notifyObserver通過呼叫觀察者的udpate方法通知觀察者狀態變化!

  Observer 是抽象觀察者,所有的觀察者都繼承這個抽象類,這個抽象類提供了udpate方法,以便目標呼叫。

  CurrentConditionDisplay、StatisticsDisplay 是具體觀察者,在這兩個類的構造方法中實現了「註冊為目標的觀察者」!

<Head First 設計模式> code:

package Observer;

public interface Subject {

    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();

}
Subject
package Observer;

import java.util.ArrayList;

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) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0) {
            observers.remove(i);
        }
    }

    public void notifyObserver() {
        for (int i =0; i< observers.size(); i++) {
            Observer observer = (Observer)observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }

    public void measurementsChanged() {
        notifyObserver();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}
WeatherData
package Observer;

public interface Observer {

    public void update(float temp, float humidity, float pressure);
}
Observer
package Observer;

public class CurrentConditionsDisplay implements Observer {

    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherDay;

    public CurrentConditionsDisplay(Subject subject) {
        this.weatherDay = subject;
        weatherDay.registerObserver(this);
    }

    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;

        display();
    }

    public void display() {
        System.out.println("temp = " + temperature + " humi = " + humidity + " press = " + pressure);
    }
}
CurrentConditionsDisplay
package com.company;

import Observer.CurrentConditionsDisplay;
import Observer.WeatherData;

public class Main {

    public static void main(String[] args) {

        WeatherData weatherData = new WeatherData();

        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);

        weatherData.setMeasurements(1, 3, 4);
    }
}
Main

結果:

temp = 1.0 humi = 3.0 press = 4.0