觀察者模式的使用場景
1.當一個抽象模型有兩個方面,其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立的改變和復用;
2.當對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變;
3.觀察者模式所做的工作其實就是在接觸耦合。讓耦合的雙方都依賴於抽象,而不依賴於具體,從而使得各自的變化都不會影響到另外一邊的變化
#include <iostream> #include <list> using namespace std; //Observer類 抽象觀察者,為所有的具體觀察者定義一個接口,在得到主題的通知時更新自己。這個接口要做更新接口。 //觀察者一般用一個抽象類或者接口實現,更新接口通常包含一個Update()方法 這個方法叫做更新方法。 class Observer { public: virtual void Update(int) = 0; }; //Subject類 可翻譯為主題或抽象通知者 一般用一個抽象類或者一個接口實現。他把所有對觀察者對象的引用保存 //在一個聚集里,每個主題都可以又任何數量的觀察者。抽象主題提供一個接口,可增加或者刪除觀察者對象 class Subject { public: virtual void Attach(Observer*) = 0; virtual void Detach(Observer*) = 0; virtual void Notify() = 0; }; //ConcreteObserver 具體觀察者 實現抽象觀察角色所要求的更新接口,以便使本身的狀態與主題的狀態相協調. //具體觀察者角色可以保存一個指向具體主題對象的引用.具體觀察者校色通常用一個具體子類實現 class ConcreteObserver : public Observer { public: ConcreteObserver(Subject* pSubject) : m_pSubject(pSubject) {} void Update(int value) { cout << "ConcreteObserver get the update. New State:" << value << endl; } private: Subject* m_pSubject; }; class ConcreteObserver2 : public Observer { public: ConcreteObserver2(Subject* pSubject) : m_pSubject(pSubject) {} void Update(int value) { cout << "ConcreteObserver2 get the update. New State:" << value << endl; } private: Subject* m_pSubject; }; //ConcreteSubject類,叫做具體主題或者具體通知者..將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時...給所有登記過的觀察者發出通知. //具體主題對象通常用一個具體子類實現. class ConcreteSubject : public Subject { public: void Attach(Observer* pObserver) { m_ObserverList.push_back(pObserver); } void Detach(Observer* pObserver) { m_ObserverList.remove(pObserver); } void Notify() { std::list<Observer*>::iterator it = m_ObserverList.begin(); while (it != m_ObserverList.end()) { (*it)->Update(m_iState); ++it; } } void SetState(int state) { m_iState = state; } private: std::list<Observer*> m_ObserverList; int m_iState; }; int main() { // Create Subject ConcreteSubject* pSubject = new ConcreteSubject(); // Create Observer Observer* pObserver = new ConcreteObserver(pSubject); Observer* pObserver2 = new ConcreteObserver2(pSubject); // Change the state pSubject->SetState(2); // Register the observer pSubject->Attach(pObserver); pSubject->Attach(pObserver2); pSubject->Notify(); // Unregister the observer pSubject->Detach(pObserver); pSubject->SetState(3); pSubject->Notify(); delete pObserver; delete pObserver2; delete pSubject; system("pause"); return 0; }
參考——https://www.cnblogs.com/carsonzhu/p/5770253.html
參考——大話設計模式
上面這個有不足之處是 萬一沒有抽象觀察者這樣的接口,通知功能就完不成了.... 而且每個通知的內容是不一樣的
#include <iostream> #include <string> #include <list> using namespace std; class Subject; //抽象觀察者 class Observer { protected: string name; Subject* sub; public: Observer(string name, Subject* sub) { this->name = name; this->sub = sub; } virtual void update() = 0; }; //具體的觀察者,看股票的 class StockObserver :public Observer { public: StockObserver(string name, Subject* sub) :Observer(name, sub) { } void update(); }; //具體的觀察者,看NBA的 class NBAObserver :public Observer { public: NBAObserver(string name, Subject* sub) :Observer(name, sub) { } void update(); }; //抽象通知者 class Subject { protected: list<Observer*> observers; public: string action; virtual void attach(Observer*) = 0; virtual void detach(Observer*) = 0; virtual void notify() = 0; }; //具體通知者,秘書 class Secretary :public Subject { void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { list<Observer*>::iterator iter = observers.begin(); while (iter != observers.end()) { if ((*iter) == observer) { observers.erase(iter); } ++iter; } } void notify() { list<Observer*>::iterator iter = observers.begin(); while (iter != observers.end()) { (*iter)->update(); ++iter; } } }; void StockObserver::update() { cout << name << " 收到消息:" << sub->action << endl; if (sub->action == "梁所長來了!") { cout << "我馬上關閉股票,裝做很認真工作的樣子!" << endl; } } void NBAObserver::update() { cout << name << " 收到消息:" << sub->action << endl; if (sub->action == "梁所長來了!") { cout << "我馬上關閉NBA,裝做很認真工作的樣子!" << endl; } } int main() { Subject* dwq = new Secretary(); //創建觀察者<br> //被觀察的對象 Observer* xs = new NBAObserver("xiaoshuai", dwq); Observer* zy = new NBAObserver("zouyue", dwq); Observer* lm = new StockObserver("limin", dwq); //加入觀察隊列 dwq->attach(xs); dwq->attach(zy); dwq->attach(lm); //事件 dwq->action = "去吃飯了!";//通知 dwq->notify(); cout << endl; dwq->action = "梁所長來了!"; dwq->notify(); return 0; }