首页 > 其他 > 详细

观察者模式

时间:2017-02-03 00:31:45      阅读:214      评论:0      收藏:0      [点我收藏+]

1.基本简介

观察者模式(又称 发布 - 订阅 模式、模型 - 视图模式、源 - 收听着模式 或 从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在他本身的状态改变时主动发出通知。这通常透过呼叫各种观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

观察者

   (Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Containter)里。

被观察者

  被观察对象发生了某种变化,从容器中得到所有注册的观察者,将变化通知观察者。

撤销观察

  观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

  观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,它可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现  - 这点为程序提供了更大的灵活性。

 

c++ Demo:

#include <iostream>
#include <set>
#include <string>
using namespace std;

class CObservable;

//观察者,纯虚基类
class CObserver
{
public:
CObserver::CObserver() {};
virtual ~CObserver() {};
virtual void Update(CObservable *pObs, void *pArg = NULL) = 0;
};

//被观察者,即Subject
class CObservable
{
public:
CObservable() :m_bChanged(false) { };
virtual ~CObservable() {};
void Attach(CObserver *pObs);
void Detach(CObserver *pObs);
void DetachAll();
void Notify(void *pArg = NULL);
bool HasChanged();
int GetObserversCount();
protected:
void SetChanged();
void ClearChanged();
private:
bool m_bChanged;
set<CObserver*> m_setObs;
};

void CObservable::Attach(CObserver *pObs)
{
if (!pObs)
return;
m_setObs.insert(pObs);
}

void CObservable::Detach(CObserver *pObs)
{
if (!pObs)
return;
m_setObs.erase(pObs);
}

void CObservable::DetachAll( )
{
m_setObs.clear();
}

void CObservable::SetChanged()
{
m_bChanged = true;
}

void CObservable::ClearChanged()
{
m_bChanged = false;
}

bool CObservable::HasChanged()
{
return m_bChanged;
}

int CObservable::GetObserversCount()
{
return m_setObs.size();
}

void CObservable::Notify(void *pArg)
{
if (!HasChanged())
return;
cout << "notifyobservers..." << endl;
ClearChanged();
set<CObserver*>::iterator iter = m_setObs.begin();
for (; iter != m_setObs.end(); iter++)
{
(*iter)->Update(this, pArg);
}
}

//具体应用类定义和实现,bloger是发布者,即被观察者(subject)
class CBloger :public CObservable
{
public:
void Publish(const string& strContent)
{
cout << "bloger public,content:" << strContent << endl;
SetChanged();
Notify(const_cast<char*>(strContent.c_str()));
}
};

//portal是发布者,即被观察者(subject)
class CPortal :public CObservable
{
public:
void Publish(const string& strContent)
{
cout << "portal public,content:" << strContent << endl;
SetChanged();
Notify(const_cast<char*>(strContent.c_str()));
}
};

//RSS 阅读器,观察者
class CRSSReader :public CObserver
{
public:
CRSSReader(const string &strName):m_strName(strName) {};
virtual void Update(CObservable *pObs, void *pArg = NULL)
{
char *pContent = static_cast<char*>(pArg);
if (dynamic_cast<CPortal*>(pObs))
{
cout << m_strName << "update from portal,content:" << pContent << endl;
}
else if(dynamic_cast<CBloger*>(pObs))
{
{
cout << m_strName << "update from CBloger,content:" << pContent << endl;
}
}
}
private:
string m_strName;
};

//Mail阅读器,观察者
class CMailReader :public CObserver
{
public:
CMailReader(const string &strName):m_strName(strName){}
virtual void Update(CObservable *pObs, void *pArg = NULL)
{
char *pContent = static_cast<char*>(pArg);
if (dynamic_cast<CPortal*>(pObs))
{
cout << m_strName << "update from portal,content:" << pContent << endl;
}
else if(dynamic_cast<CBloger*>(pObs))
{
{
cout << m_strName << "update from CBloger,content:" << pContent << endl;
}
}
}
private:
string m_strName;
};

int main()
{
CBloger *pBloger = new CBloger();
CPortal *pPortal = new CPortal();
//观察者,一个观察者可以观察多个目标
CRSSReader *pRssReader = new CRSSReader("rssreader");
CMailReader *pMailReader = new CMailReader("mail reader");
pBloger->Attach(pRssReader);
pBloger->Attach(pMailReader);
pPortal->Attach(pRssReader);
pPortal->Attach(pMailReader);

pBloger->Publish("博客分享设计模式");
cout << endl;
pPortal->Publish("门户分享设计模式");
cout << "\n portal detach mailreader" << endl;
pPortal->Detach(pMailReader);
cout << "portal observers count:" << pPortal->GetObserversCount() << endl << endl;
pPortal->Publish("门户分享设计模式");
system("pause");
return 0;
}

 

观察者模式

原文:http://www.cnblogs.com/sangtianfu/p/6361888.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!