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

設計模式之Observer模式(C++實現)

編輯:C++入門知識

觀察者模式(Observer)定義了對象間一對多的聯系。當一個對象的狀態發生變化時,所有與它有聯系的觀察者對象都會得到通知。觀察者模式將被觀察的目標和觀察者解耦,一個目標可以有任意多的觀察者,觀察者也可以觀察任意多的目標,構成復雜的聯系,而每個觀察者都不知道其他觀察者的存在。

 

這裡我就不列出那麼多正式化的UML圖了,那些是書本上的事,如果要詳細學設計模式,推薦Gof的大話設計模式

 

我們在這裡舉兩個例子來說明

第一:燒水瓶熱水時候,當燒到97度的時候,顯示屏會收到消息,然後再屏幕上顯示當前溫度,聲控器會發出聲音,提示報警!

第二:某軟件公司突然來了一個性感的女秘書,程序員A和程序員B這兩個釣絲按耐不住了,密切注視著這位女秘書,秘書的一舉一動都會影響到他們!

 

我們先來看第一個問題,仔細分析一下大多數人都會寫出如下代碼:

[cpp]
class Heater 

private: 
    signed int temperature; 
public: 
 
    //熱水機燒水  
    void BoilWater() 
    { 
        for(int i=0;i<=100;++i) 
        { 
            temperature = i; 
            if(temperature == 97) 
            { 
                ShowMSG(); 
                MakeAlert(); 
            } 
        } 
    } 
    //顯示屏顯示  
    void ShowMSG() 
    { 
        cout<<"誰快開了,當前溫度:"<<temperature<<",別再燒了"<<endl; 
    } 
    //警報器發出警報  
    void MakeAlert() 
    { 
        cout<<"Alarm:嘀嘀嘀,水已經"<<temperature<<"度了"<<endl; 
    } 
}; 

class Heater
{
private:
 signed int temperature;
public:

 //熱水機燒水
 void BoilWater()
 {
  for(int i=0;i<=100;++i)
  {
   temperature = i;
   if(temperature == 97)
   {
    ShowMSG();
    MakeAlert();
   }
  }
 }
 //顯示屏顯示
 void ShowMSG()
 {
  cout<<"誰快開了,當前溫度:"<<temperature<<",別再燒了"<<endl;
 }
 //警報器發出警報
 void MakeAlert()
 {
  cout<<"Alarm:嘀嘀嘀,水已經"<<temperature<<"度了"<<endl;
 }
};
這樣的設計雖然可以達到目的,但是方式不太好,我們知道也許燒水器,顯示屏和警報器不一定是同一個廠家生產的,所以我們應該把他們分割成幾個類,代碼如下:

 

[cpp]
//燒水器(被觀察者)  
class Heater 

private: 
    signed int temperature; 
public: 
 
    //熱水機燒水  
    void BoilWater() 
    { 
        for(int i=0;i<=100;++i) 
        { 
            temperature = i; 
            if(temperature == 97) 
            { 
                //向監聽他的兩個類發出信息  
            } 
        } 
    } 
     
}; 
//顯示屏類(觀察著)  
class show 

public: 
    void ShowMSG(int param) 
    { 
        cout<<"誰快開了,當前溫度:"<<param<<",別再燒了"<<endl; 
    } 
}; 
 
//警報器類(觀察著)  
class alarm 

public: 
    void MakeAlert(int param) 
    { 
        cout<<"Alarm:嘀嘀嘀,水已經"<<temperature<<"度了"<<endl; 
    } 

//燒水器(被觀察者)
class Heater
{
private:
 signed int temperature;
public:

 //熱水機燒水
 void BoilWater()
 {
  for(int i=0;i<=100;++i)
  {
   temperature = i;
   if(temperature == 97)
   {
    //向監聽他的兩個類發出信息
   }
  }
 }
 
};
//顯示屏類(觀察著)
class show
{
public:
 void ShowMSG(int param)
 {
  cout<<"誰快開了,當前溫度:"<<param<<",別再燒了"<<endl;
 }
};

//警報器類(觀察著)
class alarm
{
public:
 void MakeAlert(int param)
 {
  cout<<"Alarm:嘀嘀嘀,水已經"<<temperature<<"度了"<<endl;
 }
}
如果像上面的設計,顯示屏類和警報器類都在監督著燒水器的溫度,當達到97度的時候,燒水器就會像他的兩個觀察著發出信息,一邊執行必要的操作,可是在C++不像C#有委托和事件處理,所以在C++中需要用到多態的方式,利用vector來操作消息處理,相信這個例子已經很形象的講述了觀察者模式了,接下來讓我們具體實現第二個例子

 

 

例子結構如下:

IObservable,被觀察者接口

CmishuObservable,被觀察者秘書

IObserver,觀察者接口

CCoderBObserver,觀察者程序員B

CCoderAObserver觀察者程序員A

[cpp] view plaincopyprint?
class IObservable            //被觀察者接口  

 IObservable() {} 
 virtual ~IObservable() {} 
 
 virtual void AddObserver(IObserver *pObserver) = 0;  //所有被觀察者都有的操作  
    virtual void DeleteObserver(IObserver *pObserver) = 0; 
    virtual void NotifyObservers(string context) = 0; 
 
}; 
 
class CmishuObservable:public IObservable          //秘書繼承並實現了接口的函數  

private: 
 vector<IObserver *> m_ObserverList;            //用於盛裝觀察者的容器  
 typedef vector<IObserver *>::iterator Observer_iter; 
 
public: 
  
 virtual void AddObserver(IObserver *pObserver) 
 { 
  m_ObserverList.push_back(pObserver);        //把觀察者加入到容器中  
 } 
    virtual void DeleteObserver(IObserver *pObserver) //刪除觀察著  
 { 
  Observer_iter it = m_ObserverList.begin(); 
  for(;it!= m_ObserverList.end();++it) 
  { 
   if(pObserver == *it)    //這裡有點處理得不好,不該比指針,權當例子吧  
    m_ObserverList.erase(it); 
  } 
 } 
 
    virtual void NotifyObservers(string context)   //通告觀察者,以便執行更新  
 { 
  Observer_iter it = m_ObserverList.begin(); 
  for(;it != m_ObserverList.end();++it) 
   (*it)->update(context); 
 } 
 void HaveBreakfast()           //秘書的行為  
 { 
  cout<<"美女秘書:開始吃飯去了,餓了啦"<<endl; 
  this->NotifyObservers(string("開始吃飯去了,餓了啦")); 
 } 
 void HaveFun()                //秘書的行為  
 { 
  cout<<"美女秘書:人家好想去玩啊!"<<endl; 
  this->NotifyObservers(string("人家好想去玩啊!")); 
 } 
}; 
 
 
class IObserver              //觀察者接口  

public: 
 IObserver() {} 
 virtual ~IObserver() {}; 
 
 virtual void update(string context) = 0; 
}; 
 
class CCoderAObserver:public IObserver   //程序員A繼承並實現update  

private: 
 string name; 
public: 
 CCoderAObserver()  
 { 
  name = "Coder A"; 
 } 
 
 virtual void update(string context) 
 { 
  //收到消息:我好想去玩,或者去吃飯  
  //執行相應的操作  
 } 
}; 
 
class CCoderBObserver:public IObserver //程序員B並實現update  

private: 
 string name; 
public: 
 CCoderBObserver()  
 { 
  name = "Coder B"; 
 } 
 
 virtual void update(string context) 
 { 
  //收到消息:我好想去玩,或者去吃飯  
  //執行相應的操作  
 } 
}; 

class IObservable            //被觀察者接口
{
 IObservable() {}
 virtual ~IObservable() {}

 virtual void AddObserver(IObserver *pObserver) = 0;  //所有被觀察者都有的操作
    virtual void DeleteObserver(IObserver *pObserver) = 0;
    virtual void NotifyObservers(string context) = 0;

};

class CmishuObservable:public IObservable          //秘書繼承並實現了接口的函數
{
private:
 vector<IObserver *> m_ObserverList;            //用於盛裝觀察者的容器
 typedef vector<IObserver *>::iterator Observer_iter;

public:
 
 virtual void AddObserver(IObserver *pObserver)
 {
  m_ObserverList.push_back(pObserver);        //把觀察者加入到容器中
 }
    virtual void DeleteObserver(IObserver *pObserver) //刪除觀察著
 {
  Observer_iter it = m_ObserverList.begin();
  for(;it!= m_ObserverList.end();++it)
  {
   if(pObserver == *it)    //這裡有點處理得不好,不該比指針,權當例子吧
    m_ObserverList.erase(it);
  }
 }

    virtual void NotifyObservers(string context)   //通告觀察者,以便執行更新
 {
  Observer_iter it = m_ObserverList.begin();
  for(;it != m_ObserverList.end();++it)
   (*it)->update(context);
 }
 void HaveBreakfast()           //秘書的行為
 {
  cout<<"美女秘書:開始吃飯去了,餓了啦"<<endl;
  this->NotifyObservers(string("開始吃飯去了,餓了啦"));
 }
 void HaveFun()                //秘書的行為
 {
  cout<<"美女秘書:人家好想去玩啊!"<<endl;
  this->NotifyObservers(string("人家好想去玩啊!"));
 }
};


class IObserver              //觀察者接口
{
public:
 IObserver() {}
 virtual ~IObserver() {};

 virtual void update(string context) = 0;
};

class CCoderAObserver:public IObserver   //程序員A繼承並實現update
{
private:
 string name;
public:
 CCoderAObserver()
 {
  name = "Coder A";
 }

 virtual void update(string context)
 {
  //收到消息:我好想去玩,或者去吃飯
  //執行相應的操作
 }
};

class CCoderBObserver:public IObserver //程序員B並實現update
{
private:
 string name;
public:
 CCoderBObserver()
 {
  name = "Coder B";
 }

 virtual void update(string context)
 {
  //收到消息:我好想去玩,或者去吃飯
  //執行相應的操作
 }
};

 

 


 

  

 

 


 

 

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