【设计模式】观察者模式

 

 

观察者模式

适用于一个变化会引起其他多个变化

引起变化的叫【通知者】,被引起变化的叫【观察者】。 

从代码实现角度讲,【抽象通知者】需要依赖于【抽象观察者】,至少需要知道抽象观察者的类名和一个【更新函数】名。

这个模式的一般实现有点违反【面向接口编程,不要面向实现编程】,而且观察者的更新函数是同一个抽象基类的虚函数,其函数名相同(功能也是类似的功能),而不是每个观察者有不同的动作(即不必都是相同的【更新函数】)。

C#为了解决此问题,使用了在【观察者】中不用继承结构,使用委托和事件来实现,即不同的观察者中的【更新函数】各自不同,而使用委托和事件,

delegate  int  UpdateFunc(int);

UpdateFunc  func += new EventHandler(不同具体观察者的同原型的更新函数)

 在C++中在解决这个问题呢?  需要解决一个问题(没有继承结构的前提下):C#中的委托类似于C++中的函数指针,而C++中的类成员函数指针在不同类之间的转换有问题? 点解决?

/************************************************************************/
/* 设计模式
   观察者模式

   若干个【通知者】,若干个【观察者】
   【通知者】可以向【观察者】发出通知,以便让【观察者】的状态发生变化。
   【通知者】可以增减他的【观察者】,这样有一个缺点就是违反了依赖倒转原则,
   【通知者】依赖于【观察者】,即【通知者】至少需要知道【观察者】的名字和
   更新【观察者】状态的“方法”。 

   以【大话设计模式】里的讲到的Visual Studio的窗口变化为例: 
   当【启动调试】时,【输出】窗口展开,【反汇编】窗口展开
   当【结束调试】时,【输出】窗口隐藏,【反汇编】窗口隐藏
   所以这里的【通知者】为【调试器】,【观察者】为【输出】和【反汇编】窗口
/************************************************************************/

 

 调试器的两个动作:启动调试 和 停止调试

//调试器的两个行为:启动 和 停止
typedef enum _ESubjectState{Start = 0, End = 1}ESubjectState;

观察者抽象基类,窗口

//【观察者】--【窗口类】
class CWindow
{
public:
    CWindow();
    virtual ~CWindow();
    virtual void Update(ESubjectState e) = 0;  //更新状态的虚函数
};

CWindow::CWindow(){}
CWindow::~CWindow(){}

//////////////////////////////////////////////////////////////////////////

 

第一个具体观察者类, 输出窗口类

//【观察者】--【输出窗口类】
class COutputWnd : public CWindow
{
public: 
    COutputWnd();
    virtual ~COutputWnd();
    virtual void Update(ESubjectState e);  //更新状态
};

COutputWnd::COutputWnd(){}
COutputWnd::~COutputWnd(){}
void COutputWnd::Update(ESubjectState e)
{
    switch(e)
    {
    case Start:
        cout<<"调试器启动了,展开 输出窗口 
";
        break;
    case End:
        cout<<"调试器关闭了,收起 输出窗口 
";
    default:
        break;
    } 
}

第二个具体观察者,反汇编窗口类

//【观察者】--【反汇编窗口类】
class CDisassembling : public CWindow
{
public:
    CDisassembling();
    virtual ~CDisassembling();
    virtual void Update(ESubjectState e);
};

CDisassembling::CDisassembling(){}
CDisassembling::~CDisassembling(){}
void CDisassembling::Update(ESubjectState e)
{
    switch(e)
    {
    case  Start:
        cout<<"调试器启动了,展开 反汇编窗口 
";
        break;
    case End:
        cout<<"调试器关闭了,收起 反汇编窗口 
";
        break;
    default:
        break;
    }

} 

------------------------------------------------------------------------------------------------

通知者抽象类, 主题类

//【通知者】抽象类
class CSubject
{
public:
    CSubject();
    virtual ~CSubject();
    virtual void AddObserer(CWindow* pWnd)     = 0;  //添加观察者
    virtual void RemoveObserver(CWindow* pWnd) = 0;  //删除观察者
    virtual void Notify(ESubjectState e)       = 0;  //通知函数

protected:
    typedef vector<CWindow*> ObserverWnd;
    ObserverWnd m_vecObserver; 
};

CSubject::CSubject(){}
CSubject::~CSubject(){}

一个具体的通知者类, 调试器类

//【通知者】--【调试器类】
class CDebugger : public CSubject
{
public:
    CDebugger();
    virtual ~CDebugger();
    virtual void AddObserer(CWindow* pWnd);       //添加观察者
    virtual void RemoveObserver(CWindow* pWnd);   //删除观察者
    virtual void Notify(ESubjectState e);         //通知函数
};

CDebugger::CDebugger(){}
CDebugger::~CDebugger(){}

//添加观察者,当待添加的观察者不存在时才添加
void CDebugger::AddObserer(CWindow* pWnd)
{
    if(find(m_vecObserver.begin(), m_vecObserver.end(), pWnd) == m_vecObserver.end())
        m_vecObserver.push_back(pWnd);
}

//删除观察者
void CDebugger::RemoveObserver(CWindow* pWnd)
{  
    ObserverWnd::iterator iter = find(m_vecObserver.begin(), m_vecObserver.end(), pWnd);
    if(m_vecObserver.end() != iter) m_vecObserver.erase(iter);
}
void CDebugger::Notify(ESubjectState e)
{
    for (ObserverWnd::iterator iter = m_vecObserver.begin(); iter != m_vecObserver.end(); ++ iter)
    { 
        (*iter)->Update(e); 
    }  
}

客户端代码

int _tmain(int argc, _TCHAR* argv[])
{  

    //通知者
    CSubject* pSubject = new CDebugger();
    
    //三个观察者, 一个是输出窗口, 另外两个是反汇编窗口
    CWindow* pWnd1 = new COutputWnd();
    CWindow* pWnd2 = new CDisassembling();
    CWindow* pWnd3 = new CDisassembling();

    cout<<"-----------添加三个观察者------------"<<endl;
    pSubject->AddObserer(pWnd1);
    pSubject->AddObserer(pWnd2);
    pSubject->AddObserer(pWnd3);
    pSubject->Notify(Start);

    cout<<endl;

    pSubject->Notify(End);


    cout<<endl<<"----------把观察者3删除-------------"<<endl;
    pSubject->RemoveObserver(pWnd3);
    pSubject->Notify(Start);
    cout<<endl;
    pSubject->Notify(End);

    cout<<endl<<endl;

    delete pSubject; pSubject = NULL;
    delete pWnd1;    pWnd1    = NULL;
    delete pWnd2;    pWnd2    = NULL;
    delete pWnd3;    pWnd3    = NULL;

    return 0;
}

 

原文地址:https://www.cnblogs.com/cuish/p/3801044.html