简介
观察者模式,定义了对象间一对多的关系,当被观察者的状态改变时,它所依赖的所有对象都会被更新和通知。观察者模式在实际应用中较多,例如各种订阅的实现都有观察者的应用,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;
}