/*************************************************************************
> File Name: publish-subscribe.cpp
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Wed 02 May 2018 12:13:07 PM CST
************************************************************************/
#include<iostream>
#include<set>
#include<string>
#include<unistd.h>
using namespace std;
class CPublisher; // Observable
class CSubscriber { // Observer
public:
CSubscriber() {};
virtual ~CSubscriber() {};
virtual void Update(CPublisher* pPub, void* pArg = NULL) = 0;
virtual string GetName(void) const = 0;
};
class CPublisher{
public:
CPublisher() : m_bChanged(false){};
virtual ~CPublisher() {};
void Attach(CSubscriber* pSub);
void Detach(CSubscriber* pSub);
void DetachAll();
void Notify(void* pArg = NULL);
bool HasChanged();
int GetAttachedSubscriberCount();
void ListAll(void)const {
set<CSubscriber*>::iterator itr = m_setSub.begin();
for(; itr != m_setSub.end(); itr++) {
std::cout << (*itr)->GetName() << std::endl;
}
}
protected:
void SetChanged();
void ClearChanged();
private:
bool m_bChanged;
set<CSubscriber*> m_setSub;
};
void CPublisher::Attach(CSubscriber* pSub)
{
if (!pSub) return;
m_setSub.insert(pSub);
}
void CPublisher::Detach(CSubscriber* pSub)
{
if (!pSub) return;
m_setSub.erase(pSub);
}
void CPublisher::DetachAll()
{
m_setSub.clear();
}
void CPublisher::SetChanged()
{
m_bChanged = true;
}
void CPublisher::ClearChanged()
{
m_bChanged = false;
}
bool CPublisher::HasChanged()
{
return m_bChanged;
}
int CPublisher::GetAttachedSubscriberCount()
{
return m_setSub.size();
}
void CPublisher::Notify(void* pArg)
{
if (!HasChanged()) return;
cout << "notify all subscriber......" << endl;
ClearChanged();
set<CSubscriber*>::iterator itr = m_setSub.begin();
for (; itr != m_setSub.end(); itr++) {
(*itr)->Update(this, pArg);
}
}
/**
* a publisher class.
*/
class CBloger : public CPublisher {
public:
void Publish(const string& strContext) {
cout << "blog publish context: " << strContext << endl;
SetChanged();
Notify(const_cast<char*>(strContext.c_str()));
}
};
class CPortal : public CPublisher {
public:
void Publish(const string& strContext) {
cout << "protal publish context: " << strContext << endl;
SetChanged();
Notify(const_cast<char*>(strContext.c_str()));
}
};
/**
* a subscriber class.
*/
class CRSSReader : public CSubscriber {
public:
CRSSReader(const string &strName) : m_strName(strName) {}
virtual void Update(CPublisher* pPub, void* pArg = NULL) {
char* pContext = static_cast<char*>(pArg);
if (dynamic_cast<CBloger*>(pPub)) {
cout << m_strName << " updated from bloger, context: "<< pContext << endl;
} else if (dynamic_cast<CPortal*>(pPub)) {
cout << m_strName << " updated from portal, context: " << pContext << endl;
}
}
virtual string GetName(void) const {
return m_strName;
}
private:
string m_strName;
};
class CMailReader : public CSubscriber {
public:
CMailReader(const string &strName) : m_strName(strName) {}
virtual void Update(CPublisher* pPub, void* pArg = NULL) {
char* pContext = static_cast<char*>(pArg);
if (dynamic_cast<CBloger*>(pPub)) {
cout << m_strName << " updated from bloger, context: "<< pContext << endl;
} else if (dynamic_cast<CPortal*>(pPub)) {
cout << m_strName << " updated from portal, context: " << pContext << endl;
}
}
virtual string GetName(void) const {
return m_strName;
}
private:
string m_strName;
};
int main()
{
/**< publisher */
CBloger* pBloger = new CBloger();
CPortal* pPortal = new CPortal();
/**< subscriber */
CRSSReader* pRssReader = new CRSSReader("rss reader");
CMailReader* pMailReader= new CMailReader("mail reader");
/**< attach subscriber to publisher */
pBloger->Attach(pRssReader);
pBloger->Attach(pMailReader);
pPortal->Attach(pRssReader);
pPortal->Attach(pMailReader);
/**< puhlish events */
pBloger->Publish("publish a blog");
cout << endl;
pPortal->Publish("publish a choice");
cout << endl;
cout << "attached subscriber on bloger: "<< pBloger->GetAttachedSubscriberCount() << endl;
pBloger->ListAll();
cout << endl;
cout << "attached subscriber on portal: "<< pPortal->GetAttachedSubscriberCount() << endl;
pPortal->ListAll();
}
观察者模式
最新推荐文章于 2024-02-28 11:31:22 发布