C++觀察者模式
阿新 • • 發佈:2018-10-31
最近在看《headfirst 設計模式》這本書,裡面講的設計模式是基於java語言的,看完後我會利用C++來實現以加深自己的理解。先呈上觀察者模式:
觀察者模式定義了物件間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新。它主要包括了一個主題和若干個觀察者,只要一個物件註冊成為觀察者,主題狀態改變時,這個物件就能收到通知。模型如下:
這裡借用了《headfirst 設計模式》的介紹,C++裡面沒有介面,但是C++支援多重繼承,所以可以用抽象類來代替介面;程式碼實現如下:
執行結果如下:#include "stdafx.h" #include <iostream> #include <list> #include <iomanip> using namespace std; class Observer { public: virtual void update(float tmp,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 WeatherData :public Subject { public: void registerObserver(Observer* o) { observeList.push_back(o); } void removeObserver(Observer* o) { observeList.remove(o); } void notifyObservers() { for (list<Observer*>::iterator it=observeList.begin();it!=observeList.end();++it) { (*it)->update(temprature,humidity,pressure); } } void measurementsChanged() { notifyObservers(); } void setMeasurements(float temprature,float humidity,float pressure) { this->temprature=temprature; this->humidity=humidity; this->pressure=pressure; measurementsChanged(); } private: float temprature; float humidity; float pressure; list<Observer*> observeList; }; class CurrentConditonDisplay:public Observer { public: CurrentConditonDisplay(Subject *weatherdata) { this->myWeatherData=weatherdata; Subscribe(); } void update(float tmp,float humidity,float pressure) { this->temprature=tmp; this->humidity=humidity; display(); } void display() { cout<<"Current Condition: "<<setprecision(3)<<showpoint<<temprature<<"F degree and "<<setprecision(3)<<humidity<<"% humidity"<<endl; } void Subscribe() { myWeatherData->registerObserver(this); } void Unsubscribe() { myWeatherData->removeObserver(this); } private: float temprature; float humidity; Subject *myWeatherData; }; class StatisticDisplay:public Observer { public: StatisticDisplay(Subject *weatherdata) { this->myWeatherData=weatherdata; Subscribe(); this->maxTemprature=-1000; this->minTemprature=1000; } void update(float tmp,float humidity,float pressure) { this->minTemprature=min(minTemprature,tmp); this->maxTemprature=max(maxTemprature,tmp); display(); } void display() { cout<<"Max/Min Temperature= "<<setprecision(3)<<showpoint<<maxTemprature<<"/"<<setprecision(3)<<minTemprature<<endl; } void Subscribe() { myWeatherData->registerObserver(this); } void Unsubscribe() { myWeatherData->removeObserver(this); } private: float minTemprature; float maxTemprature; Subject *myWeatherData; }; int _tmain(int argc, _TCHAR* argv[]) { WeatherData *myWeatherData=new WeatherData; CurrentConditonDisplay conditionDisplay(myWeatherData); //預設成為觀察者 StatisticDisplay statisticDisplay(myWeatherData); //預設成為觀察者 myWeatherData->setMeasurements(80,65,30.4f); myWeatherData->setMeasurements(82,70,29.2f); conditionDisplay.Unsubscribe(); //取消訂閱,不再是觀察者 myWeatherData->setMeasurements(78,90,29.2f); delete myWeatherData; return 0; }