1.意圖 定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。 2.別名 依賴(Depenents),發佈-訂閱(Publish-subscribe) 3.動機 一個目標可以有任意數目的依賴它的觀察者。一旦目標的狀態發生改變,所有的觀察者都得到通知 ...
1.意圖
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
2.別名
依賴(Depenents),發佈-訂閱(Publish-subscribe)
3.動機
一個目標可以有任意數目的依賴它的觀察者。一旦目標的狀態發生改變,所有的觀察者都得到通知。作為這個通知的響應,每個觀察者都將查詢目標以使其狀態於目標的同步。
4.適用性
- 當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這二者封裝在獨立的對象中以使它們可以各自獨立改變和復用。
- 當一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變。
- 當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊耦合的。
5.結構
6.代碼實例
//Subject.h #include <memory> #include <vector> class AbstractObserver; class AbstractSubject { public: virtual void Attach(std::shared_ptr<AbstractObserver> pObserber)=0; virtual void Notify()=0; virtual void SetState(int state)=0; virtual int GetState()=0; }; class ConcreteSubject : public AbstractSubject { public: ConcreteSubject(); ~ConcreteSubject(); virtual void Attach(std::shared_ptr<AbstractObserver> pObserber); virtual void Notify(); virtual void SetState(int state); virtual int GetState(); private: std::vector<std::shared_ptr<AbstractObserver>> m_vecObservers; int m_state; };
//Observer.h #include <memory> class AbstractSubject; class AbstractObserver { public: virtual void Update()=0; }; class ConcreteObserver1 : public AbstractObserver { public: ConcreteObserver1(std::shared_ptr<AbstractSubject> pSubject); ~ConcreteObserver1(); virtual void Update(); private: std::shared_ptr<AbstractSubject> m_Subject; }; class ConcreteObserver2: public AbstractObserver { public: ConcreteObserver2(std::shared_ptr<AbstractSubject> pSubject); ~ConcreteObserver2(); virtual void Update(); private: std::shared_ptr<AbstractSubject> m_Subject; }; class ConcreteObserver3 : public AbstractObserver { public: ConcreteObserver3(std::shared_ptr<AbstractSubject> pSubject); ~ConcreteObserver3(); virtual void Update(); private: std::shared_ptr<AbstractSubject> m_Subject; };
//Subject.cpp #include "Subject.h" #include "Observer.h" ConcreteSubject::ConcreteSubject() { } ConcreteSubject::~ConcreteSubject() { } void ConcreteSubject::SetState(int state) { m_state = state; } void ConcreteSubject::Attach(std::shared_ptr<AbstractObserver> pObserver) { m_vecObservers.push_back(pObserver); } int ConcreteSubject::GetState() { return m_state; } void ConcreteSubject::Notify() { for(auto iter = m_vecObservers.begin(); iter != m_vecObservers.end(); ++iter) { (*iter)->Update(); } }
// Observer.cpp #include "Observer.h" #include "Subject.h" #include <iostream> ConcreteObserver1::ConcreteObserver1(std::shared_ptr<AbstractSubject> pSubject) : m_Subject(pSubject) { } ConcreteObserver1::~ConcreteObserver1() { } void ConcreteObserver1::Update() { std::cout << "ConcreteObserver1 Updated state:" << m_Subject->GetState() << std::endl; } ConcreteObserver2::ConcreteObserver2(std::shared_ptr<AbstractSubject> pSubject) : m_Subject(pSubject) { } ConcreteObserver2::~ConcreteObserver2() { } void ConcreteObserver2::Update() { std::cout << "ConcreteObserver2 Updated state:" << m_Subject->GetState() << std::endl; } ConcreteObserver3::ConcreteObserver3(std::shared_ptr<AbstractSubject> pSubject) : m_Subject(pSubject) { } ConcreteObserver3::~ConcreteObserver3() { } void ConcreteObserver3::Update() { std::cout << "ConcreteObserver3 Updated state:" << m_Subject->GetState() << std::endl; }
//client.cpp #include "Observer.h" #include "Subject.h" int main() { std::shared_ptr<AbstractSubject> pSubject(new ConcreteSubject); std::shared_ptr<AbstractObserver> pObserver1(new ConcreteObserver1(pSubject)); std::shared_ptr<AbstractObserver> pObserver2(new ConcreteObserver2(pSubject)); std::shared_ptr<AbstractObserver> pObserver3(new ConcreteObserver3(pSubject)); pSubject->Attach(pObserver1); pSubject->Attach(pObserver2); pSubject->Attach(pObserver3); pSubject->SetState(5); pSubject->Notify(); while(1); }
7.測試結果
8.效果
- 目標和觀察者間的抽象耦合
- 支持廣播通信
- 意外的更新 因為一個觀察者並不知道其它觀察者的存在,它可能對改變目標的最終代價一無所知。在目標上一個看似無害的操作可能會引起一系列對觀察者以及依賴於這些觀察者的那些對象的更新。此外,如果依賴準則的定義或維護不當,常常會引起錯誤的更新,這種錯誤通常難以捕捉。