程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C++設計模式—觀察者模式

C++設計模式—觀察者模式

編輯:關於C語言
 

之前做了一個性能測試的項目,就是需要對現在的產品進行性能測試,獲得測試數據,然後書寫測試報告,並提出合理化的改善意見。項目很簡單,我們獲得了一系列性能測試數據,對於數據,我們需要在Excel中制作測試數據的折線圖、餅狀圖和柱狀圖,以直觀的表現出性能的變化。在實際操作時,我發現,如果我修改了一個數據,折線圖、餅狀圖和柱狀圖就都發生了變換。這個是如何做到的?這就要說到今天總結的觀察者模式了,作為設計模式大家庭中最重要的一個,我們不得不去好好的學習一下觀察者模式。

觀察者模式

在GOF的《設計模式:可復用面向對象軟件的基礎》一書中對觀察者模式是這樣說的:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。當一個對象發生了變化,關注它的對象就會得到通知;這種交互也稱為發布-訂閱(publish-subscribe)。目標是通知的發布者,它發出通知時並不需要知道誰是它的觀察者。

再說說上面的數據和圖之間的關系;不管是折線圖、餅狀圖,還是柱狀圖,它們都依賴於數據;當數據發生變化時,數據對象會通知依賴於它的對象去更新;所以就有了Excel中,當數據發生變化時,對應的統計圖也會自動的重繪。

UML類圖

果凍想 | 一個原創文章分享網站

Subject(目標)
——目標知道它的觀察者。可以有任意多個觀察者觀察同一個目標;
——提供注冊和刪除觀察者對象的接口。

Observer(觀察者)
——為那些在目標發生改變時需獲得通知的對象定義一個更新接口。

ConcreteSubject(具體目標)
——將有關狀態存入各ConcreteObserver對象;
——當它的狀態發生改變時,向它的各個觀察者發出通知。

ConcreteObserver(具體觀察者)
——維護一個指向ConcreteSubject對象的引用;
——存儲有關狀態,這些狀態應與目標的狀態保持一致;
——實現Observer的更新接口以使自身狀態與目標的狀態保持一致。

觀察者模式按照以下方式進行協作:

  1. 當ConcreteSubject發生任何可能導致其觀察者與其本身狀態不一致的改變時,它將通知它的各個觀察者;
  2. 在得到一個具體目標的改變通知後,ConcreteObserver對象可向目標對象查詢信息。ConcreteObserver使用這些信息以使它的狀態與目標對象的狀態一致。

以下是調用時序圖:

果凍想 | 一個原創文章分享網站

使用場合

在以下任一情況下都可以使用觀察者模式:

  1. 當一個抽象模型有兩個方面,其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立的改變和復用;
  2. 當對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變;
  3. 當一個對象必須通知其它對象,而它又不能假定其它對象是誰;也就是說,你不希望這些對象是緊密耦合的。

代碼實現

#include <iostream>#include <list>using namespace std;class Observer{public:
     virtual void Update(int) = 0;};class Subject{public:
     virtual void Attach(Observer *) = 0;
     virtual void Detach(Observer *) = 0;
     virtual void Notify() = 0;};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;};class ConcreteSubject : public Subject{public:
     void Attach(Observer *pObserver);
     void Detach(Observer *pObserver);
     void Notify();

     void SetState(int state)
     {
          m_iState = state;
     }private:
     std::list<Observer *> m_ObserverList;
     int m_iState;};void ConcreteSubject::Attach(Observer *pObserver){
     m_ObserverList.push_back(pObserver);}void ConcreteSubject::Detach(Observer *pObserver){
     m_ObserverList.remove(pObserver);}void ConcreteSubject::Notify(){
     std::list<Observer *>::iterator it = m_ObserverList.begin();
     while (it != m_ObserverList.end())
     {
          (*it)->Update(m_iState);
          ++it;
     }}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;}

總結

觀察者模式在23個設計模式中的地位是非常高的,我們基本上各大框架中都是隨處可見。真正的理解了整個模式,對我們去理解別人的代碼有非常大的幫助;在我們日後的工作中也會或多或少的使用該設計模式。這裡總結的不是很全面,在日後如果碰到了需要補充的內容,我會繼續補充的;同時也希望大家提出更好的建議。

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved