乐趣区

观察者模式

简介

观察者模式,定义了对象间一对多的关系,当被观察者的状态改变时,它所依赖的所有对象都会被更新和通知。观察者模式在实际应用中较多,例如各种订阅的实现都有观察者的应用,mvc 复合模式也使用了观察者。

UML 类图

示例

有球迷关注体育新闻,球迷可以作为观察者,订阅服务可以看作 Subject,以此为例,实现观察者服务。
观察者相关,observer.h

#ifndef OBSERVER_H
#define OBSERVER_H
#include <set>
#include <string>
#include <iostream>

using namespace std;
class CObserver;
class CSubject
{
public:
    virtual void Attach(CObserver* pObserver);
    virtual void Detach(CObserver* pObserver);
    virtual void SetNews(const string& strContent) = 0;
    
protected:
    set<CObserver*> m_observerContainer;
};

class CSportSubject:public CSubject
{
public:
    virtual void Notify();
    void SetNews(const string& strContent);
    string& GetNews();
private:
    string m_strNews;
};

class CObserver
{
public:
    virtual void update(string& strContent) = 0;
    virtual void Register(CSubject* pSubject);
    virtual void UnRegister(CSubject* pSubject);
protected:
    string m_strContent;
};

class CSportObserver:public CObserver
{
public:
    CSportObserver(const string& strName):m_strName(strName){}
    void update(string& strContent);
private:
    string m_strName;
};

#endif

观察者具体实现,observer.cpp

#include "observer.h"

void CSubject::Attach(CObserver* pObserver)
{m_observerContainer.insert(pObserver);
}

void CSubject::Detach(CObserver* pObserver)
{m_observerContainer.erase(pObserver);
}

void CSportSubject::Notify()
{for(set<CObserver*>::iterator iter = m_observerContainer.begin(); iter != m_observerContainer.end(); ++iter)
    {(*iter)->update(m_strNews);
    }
}

void CSportSubject::SetNews(const string& strContent)
{
    m_strNews = strContent;
    Notify();}

string& CSportSubject::GetNews()
{return m_strNews;}
void CObserver::Register(CSubject* pSubject)
{pSubject->Attach(this);
}

void CObserver::UnRegister(CSubject* pSubject)
{pSubject->Detach(this);
}

void CSportObserver::update(string& strContent)
{
    m_strContent = strContent;
    cout<<m_strName<<":"<<strContent<<endl;
}

客户端调用,main.cpp

#include "observer.h"

#define SAFE_DELETE(p) if(p){delete (p); (p) = NULL;}
int main(int argc, char* argv[])
{
    CSubject* pSportSubject = new CSportSubject;
    CObserver* pObserverA = new CSportObserver("FansA");
    CObserver* pObserverB = new CSportObserver("FansB");
    pObserverA->Register(pSportSubject);
    pObserverB->Register(pSportSubject);

    pSportSubject->SetNews("Messi goal 3.");
    SAFE_DELETE(pObserverA);
    SAFE_DELETE(pObserverB);
    SAFE_DELETE(pSportSubject);
    return 0;
}
退出移动版