Head First 設計模式——觀察者模式(Observer Pattern)

來源:互聯網
上載者:User

觀察者模式(Observer Pattern)

定義了對象之間的一對多依賴,這樣一來,當一個對象改變狀態時,它的所有依賴者都會受到通知並且自動更新。並且有“推”和“拉”兩種通知方式。

設計原則:為了互動對象之間的松耦合設計而努力

問題:

現在需要建立一個Internet 氣象站,WeatherData 對象可以追蹤目前的天氣狀況,現在有三個布告板,分別顯示目前的狀況,氣象統計以及簡單的預報。當WeatherData擷取了最新的資料的時候,三種布告板必須即時更新。


下面來看一個例子:

鴨子物件過來告訴主題,它想當一個觀察者


鴨子物件現在已經成為正式觀察者


主題有了新資料,現在鴨子可以收到資料


老鼠對象要求從觀察者中把自己除名


老鼠離開了


主題有了新資料,老鼠接收不到


定義觀察者模式的類圖:

#include<iostream>#include<list>using namespace std;class Observer{public:virtual void update(float temp,float humidity, float pressure) = 0;};class Subject{public:virtual void registerObserver(Observer *o) = 0;virtual void removeObserver(Observer *o) = 0;virtual void notifyObservers() = 0;};class DisplayElement{public:virtual void display() = 0;};class WeatherData: public Subject{public:WeatherData(){observers.clear();}void registerObserver(Observer *o){observers.push_back(o);}void removeObserver(Observer *o){observers.remove(o);}void notifyObservers(){for( list<Observer *>::iterator it = observers.begin(); it != observers.end(); ++it){(*it)->update(temperature,humidity,pressure);}}void measurementsChanged(){notifyObservers();}void setMeasurements(float temperature, float humidity,float pressure){this->temperature = temperature;this->humidity = humidity;this->pressure = pressure;//可以根據擷取的資料來判斷要不要設定measurementsChanged();}private:list<Observer*> observers;float temperature;float humidity;float pressure;};class CurrentConditionsDisplay: public Observer,public DisplayElement{public:CurrentConditionsDisplay(Subject * weatherData){this->weatherData = weatherData;//註冊成為觀察者this->weatherData->registerObserver(this);}~CurrentConditionsDisplay(){}void update(float temperature,float humidity,float pressure){this->temperature = temperature;this->humidity = humidity;//繼承的方法被重寫display();}void display(){cout << "Current conditions:"   << temperature << "F degrees and" << humidity << "%humidity" << endl;}private:float temperature;float humidity;Subject * weatherData;};int main(){WeatherData  *weatherData = new WeatherData();CurrentConditionsDisplay *currentDisplay = new CurrentConditionsDisplay(weatherData);//可以自己定義其他的display 類型//StatisticDisplay *statisticsDisplay = new StatisticDisplay(weatherData);weatherData->setMeasurements(80,65,30.4f);weatherData->setMeasurements(82,70,29.2f);delete weatherData;delete currentDisplay;}

     上述的設計充分體現了松耦合的原則。當兩個對象之間松耦合,他們依然可以互動,但是不太清楚彼此的細節。觀察者模式提供了一種對象設計,讓主題和觀察者之間松耦合。關於觀察者的一切,主題只知道觀察者實現了某個介面(Observer 純虛類),並不需要知道觀察者的具體類是誰、做了些什麼或其他細節。任何時候我們可以增加新的觀察者。因為主題唯一依賴的東西是一個實現Observer介面的對象列表,所以我們可以隨時增加觀察者。

     假如我們有個新的具體類需要當觀察者,我們不需要為了相容新類型而修改主題的代碼,所要做的就是在新的類裡實現此觀察者的介面,然後註冊觀察者即可。


        上述的設計其實還存在一些問題,當資料改變的時候,主題“推”所有資料給觀察者,即使這些資料不是必須的(上例中的pressure資料)。觀察者模式還有另外一種思路,觀察者提供getter 方法,當需要時,觀察者來“拉”走自己所需要的資料。HeadFirst 上面是利用Java提供的介面實現的。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.