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

C++ 實現觀察者(Observer)模式詳解

編輯:C++入門知識

C++ 實現觀察者(Observer)模式詳解


觀察者(Observer)模式,是常見的模式之一。比如一份報紙,有很多訂戶。訂閱者並不知道報紙何時會送來,他只知道自己訂了這份報紙。訂閱者在這裡擔任著觀察者的角色,而報社則是被觀察者。 報紙一旦印刷完畢,就應該及時送到訂戶手中,如果將報社看作一個對象,則報紙便是觀察者(訂戶)和被觀察者(報社)之間的紐帶。觀察者需要維護一個與報紙相關的變量或函數,在這個具體問題中,這個變量就是訂戶是否收到報紙,可設置為一個布爾型,當收到時,訂戶需要更新這個變量。

下面是源碼:
// Observer.H
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include 
using namespace std;
class Observer;
/* 被觀察者接口 */
class Subject
{
public:
    Subject():m_Issue(0)
    {


    }
    void Attach(Observer *oo);//訂閱此對象
    void Detach(Observer *oo);//解除訂閱
    void Notify();//通知訂閱者更新
    void virtual Issue() = 0;//發行函數
    bool GetIssue()
    {
        return m_Issue;
    }
    ~Subject()
    {
        list::iterator iter1,iter2,temp;
        for (iter1 = m_observerList.begin(), iter2 = m_observerList.end();
        iter1 != iter2;
        )
        {
            temp = iter1;
            ++iter1;
            m_observerList.erase(temp);
        }


        m_observerList.clear();
    }
protected:
    bool m_Issue;//發行標志
    list m_observerList;//訂閱者隊列
};

/*觀察者接口*/
class Observer
{
public:
    Observer():m_receive(0){};
    void virtual Update()//更新函數
    {

    }
    void virtual ShowMessage() = 0;//模擬與被觀察者相關的函數
protected:
    bool m_receive;//收到報紙標志
};
/* 具體的被觀察者 */
class ConcreteSubject:public Subject
{
public:
    ConcreteSubject()
    {}
    void Issue();    
};
/* 具體的觀察者 */
class Subscriber1:public Observer
{
public:
    void virtual Update();
    void ShowMessage();
};
class Subscriber2:public Observer
{
public:
    void virtual Update();
    void ShowMessage();
};
#endif

被觀察者接口說明:
1.訂閱對象、解除訂閱、通知更新的函數,是所有被觀察者共有行為,所以將其抽象出來作為被觀察者的接口。
2.發行函數模擬改變狀態函數,因為不同的被觀察者有不同的方式,所以將其聲明為純虛函數,在派生類中實現。
3.觀察者用STD中的List模板來實現,所以需要析構函數來釋放。
觀察者接口說明:
1.由於所有觀察者都有更新狀態這一操作,所以將其聲明為接口。
2.Update()函數對於不同的具體對象,有不同的行為,所以在派生類中實現,聲明為純虛函數。
3.ShowMessage()函數用來模擬與被觀察者相關的操作,如果被觀察者狀態改變,觀察者需要執行某種操作,則在這裡實現。本例中用來顯示收到報紙這一信息。

下面是類的實現部分:Observer.cpp

 

#include Observer.H
#include  
#include 

/* 訂閱報紙 */
void Subject::Attach(Observer *oo)
{
    m_observerList.push_back(oo);
}


/* 取消訂閱 */
void Subject::Detach(Observer *oo)
{
    list::iterator iter;
    iter = std::find(m_observerList.begin(),m_observerList.end(),oo);
    while(iter != m_observerList.end())
    {
        m_observerList.erase(iter);
    }
}


/*通知更新*/
void Subject::Notify()
{
    list::iterator iter=m_observerList.begin();
    for ( ; iter != m_observerList.end(); iter++)
    {
        (*iter)->Update();
    }
}


/* 更改狀態 */
void ConcreteSubject::Issue()
{
    this->m_Issue = !this->m_Issue;
    if ( this->m_Issue )
    {
        cout << Magazine is Issued!
;
        this->Notify();
        this->m_Issue = false;
    }
    
}


/*訂閱者更新*/
void Subscriber1::Update()
{
    this->m_receive = true;
    this->ShowMessage();
    this->m_receive = false;
}
void Subscriber1::ShowMessage()
{
    cout << Subscriber1 has received the newspapers!
;
}


/*訂閱者更新*/
void Subscriber2::Update()
{
    this->m_receive = true;
    this->ShowMessage();
    this->m_receive = false;
}
void Subscriber2::ShowMessage()
{
    cout << Subscriber2 has received the newspapers!
;
}


下面是主程序部分:
#include Observer.H
#include 
int main()
{
    Subject *sub=new ConcreteSubject(); //被觀察者
    Observer *customer1 = new Subscriber1();//觀察者1
    Observer *customer2 = new Subscriber2();//觀察者2
    sub->Attach(customer1);//觀察者1訂閱報紙
    sub->Attach(customer2);//觀察者2訂閱報紙    
    if (sub->GetIssue())
    {
        cout << Newspapers has issued!
;
    }
    else
    {
        cout << Newspapers has not issued!
;
    }
    sub->Issue();       //發行報紙
    cout<GetIssue())
    {
        cout << Newspapers has issued!
;
    }
    else
    {
        cout << Newspapers has not issued!
;
    }
    sub->Detach(customer1);//觀察者1取消訂閱
    sub->Issue();        //發行報紙
    return 0;
}




 

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