观察者模式

56 篇文章 2 订阅
/*************************************************************************
	> 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();

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值