1. 程式人生 > >常見設計模式的解析和實現(C++)之十五-Observer模式

常見設計模式的解析和實現(C++)之十五-Observer模式

作用:
定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新.

UML結構圖:



解析:
Observer模式定義的是一種一對多的關係,這裡的一就是圖中的Subject類,而多則是Obesrver類,當Subject類的狀態發生變化的時候通知與之對應的Obesrver類們也去相應的更新狀態,同時支援動態的新增和刪除Observer物件的功能.Obesrver模式的實現要點是,第一一般subject類都是採用連結串列等容器來存放Observer物件,第二抽取出Observer物件的一些公共的屬性形成Observer基類,而Subject中儲存的則是Observer類物件的指標,這樣就使Subject和具體的Observer實現瞭解耦,也就是Subject不需要去關心到底是哪個Observer對放進了自己的容器中.生活中有很多例子可以看做是Observer模式的運用,比方說,一個班有一個班主任(Subject),他管理手下的一幫學生(Observer),當班裡有一些事情發生需要通知學生的時候,班主任要做的不是逐個學生挨個的通知而是把學生召集起來一起通知,實現了班主任和具體學生的關係解耦.

實現:
1)Observer.h
/********************************************************************
    created:    2006/07/20
    filename:     Observer.h
    author:        李創
                
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);        // 刪除物件

    
// 虛擬函式,提供預設的實現,派生類可以自己實現來覆蓋基類的實現
virtualvoid    SetState(STATE nState);    // 設定狀態
virtual STATE    GetState();        // 得到狀態

protected:
    STATE m_nSubjectState;                    
// 模擬儲存Subject狀態的變數
    std::list<Observer*>    m_ListObserver;    // 儲存Observer指標的連結串列
}
;

// Observer抽象基類
class Observer
{
public:
    Observer() : m_nObserverState(
-1){}
    
virtual~Observer(){}

    
// 純虛擬函式,各個派生類可能有不同的實現
    
// 通知Observer狀態發生了變化
virtualvoid Update(Subject* pSubject) =0;

protected:
    STATE m_nObserverState;                    
// 模擬儲存Observer狀態的變數
}
;

// ConcreateSubject類,派生在Subject類
class ConcreateSubject
    : 
public Subject
{
public:
    ConcreateSubject() : Subject()
{}
    
virtual~ConcreateSubject(){}

    
// 派生類自己實現來覆蓋基類的實現
virtualvoid    SetState(STATE nState);    // 設定狀態
virtual STATE    GetState();        // 得到狀態

}
;

// ConcreateObserver類派生自Observer
class ConcreateObserver
    : 
public Observer
{
public:
    ConcreateObserver() : Observer()
{}
    
virtual~ConcreateObserver(){}

    
// 虛擬函式,實現基類提供的介面
virtualvoid Update(Subject* pSubject);
}
;

#endif

2)Observer.cpp
/********************************************************************
    created:    2006/07/20
    filename:     Observer.cpp
    author:        李創
                
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);
    }

}


void Subject::SetState(STATE nState)
{
    std::cout 
<<"SetState By Subject\n";
    m_nSubjectState 
= nState;
}


STATE Subject::GetState()
{
    std::cout 
<<"GetState By Subject\n";
    
return m_nSubjectState;
}


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();
}


/* --------------------------------------------------------------------