【設計模式】設計模式C++編程實現之觀察者模式(ObserverPattern)

來源:互聯網
上載者:User
觀察者模式定義:定義了對象之間的一對多依賴,這樣一來,當一個對象改變狀態時,它的所有依賴者都會受到通知並自動更新。
觀察者模式又叫做發布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己

類圖
圖一 觀察者模式類圖
可以看出,在這個觀察者模式的實現裡有下面這些角色:

  1. 抽象主題(Subject)角色:主題角色把所有對觀察考對象的引用儲存在一個聚集裡,每個主題都可以有任何數量的觀察者。抽象主題提供一個介面,可以增加和刪除觀察者對象,主題角色又叫做抽象被觀察者(Observable)角色,一般用一個抽象類別或者一個介面實現。
  2. 抽象觀察者(Observer)角色:為所有的具體觀察者定義一個介面,在得到主題的通知時更新自己。這個介面叫做更新介面。抽象觀察者角色一般用一個抽象類別或者一個介面實現。在這個示意性的實現中,更新介面只包含一個方法(即Update()方法),這個方法叫做更新方法。
  3. 具體主題(ConcreteSubject)角色:將有關狀態存入具體現察者對象;在具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。具體主題角色又叫做具體被觀察者角色(Concrete Observable)。具體主題角色通常用一個具體子類實現。
  4. 具體觀察者(ConcreteObserver)角色:儲存與主題的狀態自恰的狀態。具體現察者角色實現抽象觀察者角色所要求的更新介面,以便使本身的狀態與主題的狀態相協調。如果需要,具體現察者角色可以儲存一個指向具體主題對象的引用。具體觀察者角色通常用一個具體子類實現。

觀察者模式提供了一種對象設計,讓主題和觀察者之間松耦合。 當兩個對象之間松耦合,他們依然可以互動,但是不太清楚彼此的細節。
關於觀察者的一切,主題只知道觀察者實現了某個介面(Observer)。主題不需要知道觀察者的具體類是誰、做了些什麼或其他任何細節。 任何時候我們可以增加新的觀察者。因為主題唯一依賴的東西是一個實現Observer介面的對象列表。在有新的類型的觀察者出現時,主題的代碼不需要修改。所要做的就是在新的類裡實現此觀察者介面,然後註冊為觀察者即可。 改變主題或觀察者其中一方,並不會影響另一方。因為兩者是松耦合的。
氣象站執行個體C++編程實現
(來源於《Head First設計模式》): 其類圖:
代碼:
//觀察者模式C++編程實現//author:江南煙雨//E-Mail:xiajunhust@gmail.com#include <iostream>#include <vector>#include <algorithm>using namespace std;static int setConditionTimes = 0;//記錄設定的總次數//觀察者(布告板)抽象介面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 notifyObserver() = 0;//當主題狀態改變時,通知所有觀察者};//布告板顯示class DisplayElement{public: virtual void display()= 0;};//WeatherData具體類,繼承自主題抽象類別class WeatherData:public Subject{private:vector<Observer *> observers;float temperature;float humility;float pressure;public:WeatherData(){}~WeatherData(){vector<Observer*>::iterator pos = observers.begin();for (;pos != observers.end();++pos){delete (*pos);}}void registerObserver(Observer *o){observers.push_back(o);}void removeObserver(Observer *o){vector<Observer*>::iterator pos = find(observers.begin(),observers.end(),o);if (pos != observers.end()){observers.erase(pos);}}void notifyObserver(){vector<Observer*>::iterator pos = observers.begin();for (;pos != observers.end();++pos){(*pos)->update(temperature,humility,pressure);}}//當從氣象站得到更新觀測值時,通知觀察者void messurementsChanged(){notifyObserver();}//設定氣象站觀測值void setMessurements(float temperature,float humility,float pressure){++setConditionTimes;this->temperature = temperature;this->humility = humility;this->pressure = pressure;messurementsChanged();}};//布告板具體類:目前狀況class CurrentConditionDisplay:public Observer,public DisplayElement{private:float temperature;float humility;Subject *weatherData;public: CurrentConditionDisplay(Subject *weatherData){this->weatherData = weatherData;weatherData->registerObserver(this);}~CurrentConditionDisplay(){}void update(float temp,float humi,float pressure){this->temperature = temp;this->humility = humi;display();}void display(){cout << "Current conditions: " << temperature << "F degrees and " <<humility << "% humility" << endl;}};//布告板具體類:氣象統計類class WeatherStatisticsDisplay:public Observer,public DisplayElement{private:float avgTemperatuere,maxTemperature,minTemperature;Subject *weatherData;public: WeatherStatisticsDisplay(Subject *weatherData){this->weatherData = weatherData;weatherData->registerObserver(this);}~WeatherStatisticsDisplay(){}void update(float temp,float humi,float pressure){if (1 == setConditionTimes){this->avgTemperatuere = temp;this->maxTemperature = temp;this->minTemperature = temp;}else{this->avgTemperatuere = (this->avgTemperatuere * (setConditionTimes - 1) + temp) / setConditionTimes;this->maxTemperature = this->maxTemperature > temp ? this->maxTemperature : temp;this->minTemperature = this->minTemperature < temp ? this->minTemperature : temp;}display();}void display(){cout << "Avg/Max/Min: temperature  " << avgTemperatuere << "/" << maxTemperature << "/" <<minTemperature << endl;}};int main(){WeatherData *weatherData = new WeatherData();CurrentConditionDisplay *currentConditionDisplay = new CurrentConditionDisplay(weatherData);WeatherStatisticsDisplay *weatherStatisticsDisplay = new WeatherStatisticsDisplay(weatherData);weatherData->setMessurements(80,65,30.4f);weatherData->setMessurements(82,70,29.2f);weatherData->setMessurements(78,90,29.2f);weatherData->removeObserver(weatherStatisticsDisplay);cout << "after remove observer WeatherStatisticsDisplay:" << endl;weatherData->setMessurements(80,65,30.4f);weatherData->setMessurements(82,70,29.2f);weatherData->setMessurements(78,90,29.2f);return 0;}

運行結果(VS2008 + Win7):

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.