Observer/Event觀察者模式(C++)
阿新 • • 發佈:2018-12-30
動機: 在軟體構建過程中,我們需要為某些物件建立一種“通知依賴關係”--一個物件(目標物件)的狀態發生改變,所有的依賴物件(觀察者物件)都將得到通知。如果這樣的依賴關係過於緊密,將使軟體不能很好地抵禦變化。 使用面向物件技術,可以將這種依賴關係弱化,並形成一種穩定的依賴關係。從而實現軟體體系結構的鬆耦合。 鬆耦合可以體現在下面幾種情況: 1)一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這些方面封裝在獨立的物件中使它們可以各自獨立地改變和複用。 2)一個物件的改變將導致其他一個或多個物件也發生改變,而不需要知道具體有多少物件、
舉例: 對同一組資料進行統計分析時候, 我們希望能夠提供多種形式的表示 (例如以表格進行統計顯示、柱狀圖統計顯示、百分比統計顯示等)。這些表示都依賴於同一組資料, 我們當然需要當資料改變的時候, 所有的統計的顯示都能夠同時改變。 Observer 模式就是解決了這一個問題。
總結:解決一對多的問題,同時保證觀察者與被觀察者之間為鬆耦合。
下面程式碼展示了Observer模式的整個框架和流程。
#include <iostream> #include <list> using namespace std; class Observer; //抽象被觀察者 class Subject { public: virtual void Attach(Observer *) = 0; virtual void Detach(Observer *) = 0; virtual void Notify() = 0; virtual int GetState() { return state_; } void SetState(int state) { state_ = state; } protected: std::list<Observer *> observer_list_; int state_; }; //抽象觀察者 class Observer { public: Observer(Subject *sub):p_subject_(sub){} virtual void Update() = 0; protected: Subject* p_subject_; }; //具體觀察者1 class Observer1 : public Observer { public: Observer1(Subject *p_subject) : Observer(p_subject) {} void Update() override { cout << "Observer1 get the update:" << p_subject_->GetState() << endl; } }; //具體觀察者2 class Observer2 : public Observer { public: Observer2(Subject *p_subject) : Observer(p_subject) {} void Update() override { cout << "Observer2 get the update:" << p_subject_->GetState() << endl; } }; //具體被觀察者 class ConcreteSubject : public Subject { public: void Attach(Observer *pObserver) override { observer_list_.push_back(pObserver); } void Detach(Observer *pObserver) override { observer_list_.remove(pObserver); } void Notify() override ; }; //核心操作:迴圈通知所有觀察者 void ConcreteSubject::Notify() { auto it = observer_list_.begin(); while (it != observer_list_.end()) { (*it++)->Update(); } } int main() { // 建立被觀察者 Subject *p_subject = new ConcreteSubject(); // 建立觀察者 Observer *p_observer1 = new Observer1(p_subject); Observer *p_observer2 = new Observer2(p_subject); // 改變狀態 p_subject->SetState(2); // 註冊觀察者 p_subject->Attach(p_observer1); p_subject->Attach(p_observer2); p_subject->Notify(); // 登出觀察值 p_subject->Detach(p_observer1); p_subject->SetState(3); p_subject->Notify(); delete p_observer1; delete p_observer2; delete p_subject; }