1. 程式人生 > >Head First 設計模式(二)觀察者模式

Head First 設計模式(二)觀察者模式

觀察者模式

定義

首先看下觀察者模式的定義

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

按我自己的理解翻譯就是:

觀察者模式就是一個主題和多個依賴者的關係,當主題發生變化時,依賴者得到通知發生對應的變化。用氣象站的例子解釋:當氣象站(主題)檢測到天氣情況的改變時,會通知不同的顯示器(依賴者)顯示出天氣的情況。同時,由於顯示器自身的不同,顯現資訊也不一樣,如氣壓顯示器顯示氣壓,溼度顯示器顯示溼度。

程式碼

我們以定義中的氣象站為例。

框架

首先給出一個大概的框架:

主要分為了兩個介面:主題介面

依賴者(Observer,也稱觀察者)介面

  1. 主題類中組合了它的依賴者們,所以介面定義了增加依賴者registerObserver()、刪除依賴者removeObserver()、以及主題發生變化時通知依賴者變化的方法notifyObservers()

  2. 依賴者介面定義了專門給主題類呼叫的方法update(),主題類通過呼叫依賴類的該方法來改變依賴類。另外還有一個display()方法來顯示出依賴類的改變

詳細程式碼

接下來我們用具體的程式碼來說明。程式碼中的主題和依賴者,分別繼承和實現了Java.utilObservableObserver,這是Java中封裝好的觀察者模式類,有興趣的可以看下原始碼。

為了更清晰瞭解觀察者模式,我覆蓋了父類的實現。

主題類

值得注意的地方是,主題通知依賴類,有兩種方式:推和拉。

推就是把固定的資料傳給依賴類的方法,拉就是把主題傳給依賴類,依賴類自己調主題的方法來獲取資料。

/**
 * 氣象站(觀察者模式中的主題)
 */
public class WeatherData extends Observable{
    /**溫度*/
    private float temperature;
    /**溼度*/
    private float humidity;
    /**氣壓*/
    private float pressure;

    /**該主題的依賴者集合*/
private Vector<Observer> observers = new Vector<>(); /**主題改變標誌,用於控制 主題的改變觸發依賴類的改變的條件*/ private Boolean isChange = false; public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } /** * 增加觀察者 */ @Override public synchronized void addObserver(Observer observer){ observers.addElement(observer); } /** * 刪除觀察者 */ @Override public synchronized void deleteObserver(Observer observer){ observers.addElement(observer); } /** * 通知觀察者(拉) */ @Override public void notifyObservers(){ notifyObservers(null); } /** * 通知觀察者(推) */ @Override public synchronized void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!isChange) return; arrLocal = observers.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } @Override public void setChanged() { isChange = true; } /** * 每次資料改動後呼叫的方法 */ public void measurementsChanged(){ setChanged(); //將主題傳給依賴類,依賴類呼叫主題的方法自己"拉取"資料 notifyObservers(); //將固定的資料"推"給依賴類,依賴類只能獲取指定的資料 /*Map<String, Float> args = new HashMap<>(); args.put("temperature", temperature); args.put("humidity", humidity); args.put("pressure", pressure); notifyObservers(args);*/ } /** * 模擬資料改動 */ public void setMeasurements(float temp, float humidity, float pressure){ this.temperature = temp; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } }

依賴類(觀察者類)

由於他們都要顯示出氣象站的資料,所以定義了一個公共展示介面

public interface Display {
    public void display();
}

第一個依賴類,假設只顯示氣壓和溫度

/**
 * 依賴類,當氣象站資料發生改變時,顯示資料
 */
public class StatisticsDisplay implements Observer,Display{
    /**主題*/
    private Observable observable;
    private float temperature;
    private float pressure;

    public StatisticsDisplay(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }
    @Override
    public void update(Observable o, Object arg) {
        //推的方式獲取資料
        /*if (arg instanceof HashMap) {
            HashMap<String, Float> args = (HashMap<String, Float>) arg;
            this.temperature = args.get("temperature");
            this.pressure = args.get("pressure");

            display();
        }*/

        //拉的方式獲取資料
        if(o instanceof WeatherData){
            WeatherData weatherData = (WeatherData) o;
            this.temperature = weatherData.getTemperature();
            this.pressure = weatherData.getPressure();

            display();
        }
    }

    @Override
    public void display() {
        System.out.println("TEMP/PRESSURE:"+temperature+" /"+ pressure);
    }

}

第二個依賴類,假設只顯示溫度和溼度:

/**
 * 依賴類,當氣象站資料發生改變時,顯示資料
 */
public class CurrentConditionDisplay implements Observer,Display{
    /**主題*/
    private Observable observable;
    private float temperature;
    private float humidity;

    public CurrentConditionDisplay(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        //推的方式獲取資料
        /*if (arg instanceof HashMap) {
            HashMap<String, Float> args = (HashMap<String, Float>) arg;
            this.temperature = args.get("temperature");
            this.humidity = args.get("humidity");

            display();
        }*/

        //拉的方式獲取資料
        if(o instanceof WeatherData){
            WeatherData weatherData = (WeatherData) o;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();

            display();
        }
    }

    @Override
    public void display() {
        System.out.println("Current condition:"+temperature+" F degree and "+humidity +"% humidity");
    }

}

測試

public class Main {

    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionDisplay conditionDisplay = new CurrentConditionDisplay(weatherData);
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);

        weatherData.setMeasurements(80, 65, 30.4F);
        weatherData.setMeasurements(76, 79, 40.4F);
        weatherData.setMeasurements(92, 75, 20.4F);
    }
}/**output:
TEMP/PRESSURE:80.0 /30.4
Current condition:80.0 F degree and 65.0% humidity
TEMP/PRESSURE:76.0 /40.4
Current condition:76.0 F degree and 79.0% humidity
TEMP/PRESSURE:92.0 /20.4
Current condition:92.0 F degree and 75.0% humidity
**/

相關推薦

Head First 設計模式觀察模式

觀察者模式 定義 首先看下觀察者模式的定義 觀察者模式定義了物件之間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新 按我自己的理解翻譯就是: 觀察者模式就是一個主題和多個依賴者的關係,當主題發生變化

設計模式—— 觀察模式

pda 發出 dex obs index observe target 獲取 委托事件 觀察者模式類似出版社與訂閱者的關系,訂閱者能夠收到出版社發出的消息,可以取消訂閱。出版社在觀察者模式中稱為主題(Subject)訂閱者稱為觀察者(Observer)。 主

一看就懂【來自英雄聯盟蓋倫的怒吼】與 Python 詳解設計模式觀察模式

觀察者模式概述 觀察者模式(有時又被稱為模型-檢視(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統

Unity遊戲設計模式觀察模式Observer Pattern

        最近看遊戲設計模式,當看到觀察者模式時被搞得雲裡霧裡的,什麼觀察者,被觀察者,抽象觀察者,抽象被觀察者。聽著這些詞就覺得可怕,其實理解以後還是比較簡單的。         當我們玩遊戲時,經常會出現一些事件,而這個事件可能會影響到許多個模組時就可以用到觀察者

Head First設計模式觀察模式

通過具體實現一個氣象監測系統來理解觀察者模式此係統的三個部分是氣象站(獲取實際氣象資料的物理裝置)、WeatherData物件(追蹤來自氣象站的資料,並更新佈告板)和佈告板(顯示目前天氣狀況給使用者看)。 具體來說該應用需要:利用WeatherDate物件從氣象站取得資料,

設計模式學習觀察模式C#

original pan 學習筆記 pri 接口 program date contain 兩個 《深入淺出設計模式》學習筆記第二章 需求: 開發一套氣象監測應用,如圖: 氣象站,目前有三種裝置,溫度、濕度和氣壓感應裝置。 WeatherData對象追蹤氣象站的數據,並更

設計模式觀察監聽者模式

blog virtual ack memory message efault share default IT 基於MAP線程安全的觀察者監聽者模式 1 #include<map> 2 #include<string> 3 #i

設計模式觀察模式

針對 ray 需求 als bool 模式 null rri 主動 觀察者模式 定義了對象之間的一對多的依賴,這樣一來,當一個對象狀態改變時,他的 多有依賴都會受到通知並自動更新。 本例為一個溫度基站,和三個終端。溫度基站為廣播類WeatherData,三個終端監聽者類分別

設計模式18觀察模式

模式介紹 觀察者模式試圖允許物件在其內部狀態改變時通知觀察者。 這意味著單個物件需要知道觀察它的物件,並且當狀態發生變化的時候,需要能夠與那些觀察者通訊。此外,觀察者應該被自動通知。 示例 設想我們需要一個系統來建模本地蔬菜市場中蔬菜價格的波動。 我們需要允許餐館檢視價格,並在特定蔬菜的價格低於指定閾

PHP設計模式5—— 觀察模式

基本概念 整個觀察者模式,其實做的就是監聽事件、處理事件。 由此引出兩個角色,一個是觀察者Listener,另一個是事件處理者Handler。 例子 第一步,建立抽象事件類。 它的主要作用是提供兩個方法給具體事件類呼叫。 abstract clas

設計模式觀察模式

繼續設計模式的文章,今天給大家帶來觀察者模式。先來看看觀察者模式的定義:定義了物件之間的一對多的依賴,這樣一來,當一個物件改變時,它的所有的依賴者都會收到通知並自動更新。好了,對於定義的理解總是需要例項來解析的,如今的微信服務號相當火啊,下面就以微信服務號為背景,給大家介紹

Java設計模式4--觀察模式

今天看了一下觀察者模式,總體來說不難,關鍵是要知道原理和這個模式的用法下面是我自己個人一些理解。 1、定義 觀察者模式,首先得有觀察者,一個或者多個觀察者,它們都依賴於另一個物件,也就是說,這些觀察者都觀察著一個被觀察者。那麼,當被觀察者狀態發生改變

java設計模式1觀察模式

說到java觀察者模式 簡單點一個例子就是 被觀測方通過提供註冊介面,使得觀測方能夠通過註冊使得自己實時掌握被觀測方資料變化。 好了 接下來是程式碼 被觀測目標的介面,繼承這個類的目標天生自帶 拉人 踢人技能。只有被邀請的人才能看 1.subject.ava pac

Java 設計模式觀察模式

一、定義 觀察者模式定義了一個一對多的依賴關係,讓多個觀察者物件同時監聽同一個主題物件。當這個主題狀態發生改變時,會通知所有觀察者物件,讓它們自動更新自己。 二、類似場景 聊天室程式的建立。伺服器建立好後,A、B、C三個客戶端連線好公開聊天。A向

設計模式-觀察模式、C#委託、事件

書中引出的例子為,當Boss回來,前臺通知員工好好工作的場景。1、觀察模式將通知廣播給每一個客戶端,客戶端想知道目標的變化a、從目標拉取 b、通知的時候將變化傳遞給客戶端。拉取的方法,客戶端自由度較高,客戶端可以根據需求拉取。觀察者通知內容豐富,客戶端需要不要更新拉取變化。耦

設計模式: 工廠模式

dem blank hibernate 執行 oid code 做出 void actor 工廠模式 工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。 在工廠模式中,我們在創建

設計模式---工廠方法模式

ack cto sys alt 修改 spa 抽象類 .com desc 1、簡介:工廠方法模式是類的創建模式,又叫虛擬構造子模式或是多態性工廠模式,它的實現方式是創建一個工廠接口,將實際創建對象的的工作轉移到工廠子類中,在系統的擴展中,可以在不修改工廠角色的情況下引進新的

常用的JavaScript設計模式Factory(工廠)模式

asc 我們 對象實例 actor 通過 汽車 對象 UNC cti Factory通過提供一個通用的接口來創建對象,同時,我們還可以指定我們想要創建的對象實例的類型。 假設現在有一個汽車工廠VehicleFactory,支持創建Car和Truck類型的對象實例,現在需要通

設計模式:裝飾模式

實體 裝飾者 java string rgs 大氣 sta 接口 rri 2018國慶黃金周來了,恰值國慶黃金周節假日,我想高速上一定車山車海,還好我選擇了高鐵,不然肯定需要尋找項目合作人或在高速上吃創業人士的炒飯炒面了。 國慶7天長假,天氣又如此的好,所謂風和日麗,如此良