[設計模式]Observer觀察者模式

來源:互聯網
上載者:User
問題

Observer模式應該可以說是應用最多,影響最廣的模式之一,因為Observer的一個執行個體Model/View/Control(MVC)結構在系統開發架構設計中有著很重要的地位和意義,MVC實現了商務邏輯和展示層的解耦。在MFC中,Doc/View(文檔視圖結構)提供了實現MVC的架構結構。還有在事件處理系統中也經常用到。

將一個系統分割成一系列相互協作的類有一個很不好的副作用,就是需要維護相關對象間的一致性。我們不希望為了維護一致性而使各類緊密耦合,這樣會給維護,擴充和重用帶來不便。

Observer模式要解決的問題為:建立一個一(Subject)對多(Observer)的依賴關係,並且做到"一"變化的時候,依賴這個"一"的多也能夠同步改變。最常見的一個例子就是:對同一組資料進行統計分析時候,我們希望能夠提供多種形式的表示(表格統計顯示,柱狀圖統計顯示,百分比統計顯示)。這些表示都依賴於同一組資料,我們當然需要當資料改變的時候,所有的統計顯示都能夠同時改變。Observer模式就是解決這種一對多的依賴關係(耦合關係)的問題。

應用執行個體

應用多個對象依賴同一個對象的情況。其中這(多個對象是觀察者),這(一個對象是被觀察者)。

1.老師的電話號碼改變時自動通知學生。 2.對同一組資料用不同的圖片表現出來(條形,柱狀,百分圖)。

觀察者模式

觀察者模式又叫做發布-訂閱(Publish/Subscribe)模式,目標就是通知的發行者,觀察者則是通知的訂閱者(接受通知)。

定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動重新整理。

 

抽象主題(Subject):它把所有觀察者對象的引用儲存到一個聚集裡,每個主題都可以有任何數量的觀察者。抽象主題提供一個介面,可以增加,刪除觀察者對象,並且提供了觀察者同步的操作(Notify).

具體主題(ConcreteSubject):將有關狀態引入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。

抽象觀察者(Observer):為所有具體觀察者定義一個介面,在得到主題通知時更新自己。

具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新介面,以便使本身的主題狀態協調。

Observer模式實現的要點是:

1.一般Subject類都是採用鏈表等容器來存放Observer對象

2.抽取出Observer對象的一些公用屬性形成Observer基類,而Subject中儲存的則是Observer類對象的指標,這樣就使Subject和具體的Observer實現瞭解耦,也就是Subject不需要去關心到底是哪個Observer對放進了自己的容器中。 

小demo

Observer.h

/********************************************************************created:2006/07/20filename: Observer.hauthor:李創http://www.cppblog.com/converse/purpose:Observer模式的示範代碼*********************************************************************/#ifndef OBSERVER_H#define OBSERVER_H#include <list>typedef int STATE;class Observer;// Subject抽象基類,只需要知道Observer基類的聲明就可以了,可以譯為主題或抽象通知者。//實現觀察者模式的形式其實就是"註冊——通知——登出"class Subject{public:Subject() : m_nSubjectState(-1){}virtual ~Subject();void Notify();// 通知所有觀察者對象void Attach(Observer *pObserver);// 新增一個觀察者對象void Detach(Observer *pObserver);// 刪除一個觀察者對象// 虛函數,提供預設的實現,衍生類別可以自己實現來覆蓋基類的實現virtual voidSetState(STATE nState)=0;// 設定狀態virtual STATEGetState()=0;// 得到狀態protected:STATE m_nSubjectState;// 類比儲存Subject狀態的變數std::list<Observer*>m_ListObserver;// 儲存Observer指標的鏈表}; //Observe類,抽象觀察者,為所有的具體觀察者定義一個介面,在得到主題通知時更新自己。這個介面叫做更新介面。更新介面通常包含一個Update()方法,這個方法叫做更新方法class Observer{public:Observer() : m_nObserverState(-1){}virtual ~Observer(){}// 純虛函數,各個衍生類別可能有不同的實現// 通知Observer狀態發生了變化virtual void Update(Subject* pSubject) = 0;protected:STATE m_nObserverState;// 類比儲存Observer狀態的變數};// ConcreateSubject類,派生在Subject類,叫做具體主題或具體通知者class ConcreateSubject: public Subject{public:ConcreateSubject() : Subject(){}virtual ~ConcreateSubject(){}// 衍生類別自己實現來覆蓋基類的實現,是成對出現的,由Subject來設定狀態,由Observer來得到改變的狀態virtual voidSetState(STATE nState);// 設定狀態virtual STATEGetState();// 得到狀態};// ConcreateObserver類派生自Observerclass ConcreateObserver : public Observer {public: ConcreateObserver():Observer(){}ConcreateObserver(Subject* sub);//使用其建構函式,省去了在其外部調用sub->Attachvirtual ~ConcreateObserver(){}// 虛函數,實現基類提供的介面virtual void Update(Subject* pSubject);};#endif

Observer.cpp

/********************************************************************created:2006/07/20filename: Observer.cppauthor:李創http://www.cppblog.com/converse/purpose:Observer模式的示範代碼*********************************************************************/#include "Observer.h"#include <iostream>#include <algorithm>/* --------------------------------------------------------------------|Subject類成員函數的實現  ----------------------------------------------------------------------*/void Subject::Attach(Observer *pObserver){std::cout << "Attach an Observer\n";m_ListObserver.push_back(pObserver);}void Subject::Detach(Observer *pObserver){std::list<Observer*>::iterator iter;iter = std::find(m_ListObserver.begin(), m_ListObserver.end(), pObserver);if (m_ListObserver.end() != iter){m_ListObserver.erase(iter);}std::cout << "Detach an Observer\n";}void Subject::Notify(){std::cout << "Notify Observers's State\n";std::list<Observer*>::iterator iter1, iter2;for (iter1 = m_ListObserver.begin(), iter2 = m_ListObserver.end(); iter1 != iter2;++iter1){(*iter1)->Update(this);}} Subject::~Subject(){std::list<Observer*>::iterator iter1, iter2, temp;for (iter1 = m_ListObserver.begin(), iter2 = m_ListObserver.end();iter1 != iter2;){temp = iter1;++iter1;delete (*temp);}m_ListObserver.clear();}/* --------------------------------------------------------------------|ConcreateSubject類成員函數的實現 ----------------------------------------------------------------------*/void ConcreateSubject::SetState(STATE nState){std::cout << "SetState By ConcreateSubject\n";m_nSubjectState = nState;//Notify();也可以寫在內部,這樣就不用每次調用SetState()後在調用Notify()}STATE ConcreateSubject::GetState(){std::cout << "GetState By ConcreateSubject\n";return m_nSubjectState;}/* --------------------------------------------------------------------|ConcreateObserver類成員函數的實現 ----------------------------------------------------------------------*/ ConcreateObserver::ConcreateObserver(Subject* sub) : Observer(){sub->Attach(this);}void ConcreateObserver::Update(Subject* pSubject){if (NULL == pSubject)return;m_nObserverState = pSubject->GetState(); std::cout << "The ObeserverState is " << m_nObserverState << std::endl;}

Main.cpp

/********************************************************************created:2006/07/21filename: Main.cppauthor:李創http://www.cppblog.com/converse/purpose:Observer模式的測試代碼*********************************************************************/#include "Observer.h"#include <iostream>int main(){Subject* p = new ConcreateSubject();Observer *p1 = new ConcreateObserver(p);Observer *p2 = new ConcreateObserver(p);//等價於Observer *p2 = new ConcreateObserver();p->Attach(p2); p->SetState(4);p->Notify();    std::cout<<"-----------------------"<<std::endl;p->Detach(p1);p->SetState(10);p->Notify();delete p;system("pause");return 0;}/************************************************************************ 代碼說明:在Observer模式的實現中,Subject維護一個List作為儲存其所有觀察者的容器。每當調用Notify操作就遍曆List中Observer對象,並廣播通知改變狀態了(調用Observer的Update操作)。目標的狀態state可以有Subject自己改變,也可以有Observer的某個操作引起state的改變(可調用Subject的SetState操作)當然,可以有多個Subject子類,和多個Observer的子類,也可以有多個要通知的訊息。************************************************************************/

 輸出結果

觀察者模式的實質

觀察者模式所做的工作其實就是在解除耦合。讓耦合的雙方都依賴於抽象,而不是依賴於具體。從而使得各自的變化都不會影響另一邊的變化。 

聯繫我們

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