1. 程式人生 > >訂閱釋出模式——C++實現

訂閱釋出模式——C++實現

只是自己的一個記錄過程,不做詳細解說

這是這次寫的一個流程

Observer.h

#ifndef _OBSERVER_H_
#define _OBSERVER_H_

#include <map>
#include <mutex>

using namespace std;

class Msg
{
public:
	virtual int GetMsgID() = 0;

	virtual void* GetMsg() = 0;

};

class MsgContainer;

class Subscriber
{
public:
	virtual void subscribe(MsgContainer *pMsgContainer, int MsgID);

	virtual void unsubscribe(MsgContainer *pMsgContainer, int MsgID);

	virtual void handleMsg(Msg *msg) = 0;
};

class MsgContainer
{
public:
	virtual void add_subscriber(Subscriber *pSubscriber, int MsgID);

	virtual void remove_subscriber(Subscriber *pSubscriber, int MsgID);

	virtual void receiveMsg(Msg *msg);

protected:
	virtual void notify(Msg *msg);

private:
	multimap<int, Subscriber*> m_subscriber;
	mutex m_mutex;
};

class Publisher
{
public:
	virtual void sendMsg(MsgContainer *pMsgContainer, Msg *msg);
};

class MsgImp :public Msg
{
public:
	MsgImp(int MsgID, void *Msgfield);

	virtual ~MsgImp();

	virtual int GetMsgID();

	virtual void* GetMsg();

private:
	int m_MsgID;

	void *m_Msgfield;
};

class SubscriberImp :public Subscriber
{
public:
	SubscriberImp();

	virtual ~SubscriberImp();

	virtual void handleMsg(Msg *msg);
private:
	void *m_expext_field;
};

class SubscriberImp2 :public Subscriber
{
public:
	SubscriberImp2();
	virtual ~SubscriberImp2();

	virtual void handleMsg(Msg *msg);
private:
	void *m_expext_field;
};

class PublisherImp :public Publisher
{
public:
	PublisherImp();

	virtual ~PublisherImp();
};

#endif
observer.cpp
#include "Observer.h"
#include <iostream>

using namespace std;


MsgImp::MsgImp(int MsgID, void *Msgfield)
{
	m_MsgID = MsgID;
	m_Msgfield = Msgfield;
}

MsgImp::~MsgImp()
{

}

int MsgImp::GetMsgID()
{
	return m_MsgID;
}

void * MsgImp::GetMsg()
{
	return m_Msgfield;
}

void Subscriber::subscribe(MsgContainer *pMsgContainer, int MsgID)
{
	pMsgContainer->add_subscriber(this, MsgID);
}

void Subscriber::unsubscribe(MsgContainer *pMsgContainer, int MsgID)
{
	pMsgContainer->remove_subscriber(this, MsgID);
}

SubscriberImp::SubscriberImp()
{

};

SubscriberImp::~SubscriberImp()
{
	delete m_expext_field;
};

void SubscriberImp::handleMsg(Msg *msg)
{
	m_expext_field = msg->GetMsg();
	
	cout << "this is the SubscriberImp1..." << endl;
	cout << "the MsgID is " << msg->GetMsgID() << endl;
	cout <<(char *) msg->GetMsg() << ", SubscriberImp1 handle the msg"<<endl;
}

SubscriberImp2::SubscriberImp2()
{

};

SubscriberImp2::~SubscriberImp2()
{
	delete m_expext_field;
};

void SubscriberImp2::handleMsg(Msg *msg)
{
	m_expext_field = msg->GetMsg();
	
	cout << "this is the SubscriberImp2..." << endl;
	cout << "the MsgID is " << msg->GetMsgID() << endl;
	cout << (char *)msg->GetMsg() << ", SubscriberImp2 handle the msg"<< endl;
}

void MsgContainer::add_subscriber(Subscriber *pSubscriber, int MsgID)
{
	lock_guard<mutex> guard(m_mutex);

	if (m_subscriber.empty())
	{
		m_subscriber.insert(make_pair(MsgID, pSubscriber));
	}

	bool isExist = false;
	map<int, Subscriber*>::iterator it = m_subscriber.lower_bound(MsgID);
	while (it != m_subscriber.upper_bound(MsgID))
	{
		if (it->second == pSubscriber)
			isExist = true;
		it++;
	}
	if (!isExist)
	{
		m_subscriber.insert(make_pair(MsgID, pSubscriber));
	}
}

void MsgContainer::remove_subscriber(Subscriber *pSubscriber, int MsgID)
{
	lock_guard<mutex> guard(m_mutex);

	if (m_subscriber.empty())
	{
		return;
	}

	multimap<int, Subscriber*>::iterator it = m_subscriber.lower_bound(MsgID);
	while (it != m_subscriber.upper_bound(MsgID))
	{
		if (it->second == pSubscriber)
		{
			m_subscriber.erase(it);
			break;
		}
		it++;
	}
}

void MsgContainer::notify(Msg *msg)
{
	multimap<int, Subscriber*>::iterator it = m_subscriber.lower_bound(msg->GetMsgID());
	for (; it != m_subscriber.upper_bound(msg->GetMsgID()); it++)
	{
		it->second->handleMsg(msg);
	}
}

void MsgContainer::receiveMsg(Msg *msg)
{
	lock_guard<mutex> guard(m_mutex);

	this->notify(msg);
}


void Publisher::sendMsg(MsgContainer *pMsgContainer, Msg *msg)
{
	pMsgContainer->receiveMsg(msg);
}

PublisherImp::PublisherImp(){};
PublisherImp::~PublisherImp(){};



test.cpp
#include "Observer.h"
#include <iostream>

using namespace std;

int main()
{
	Subscriber *subscriber = NULL;
	MsgContainer *msgcontainer = new MsgContainer();
	Msg *msg = NULL;
	Publisher *publisher = NULL;

	char *msgfield = NULL;

	subscriber = new SubscriberImp();
	subscriber->subscribe(msgcontainer, 2);

	Subscriber *subscriber2 = NULL;
	subscriber2 = new SubscriberImp2();
	subscriber2->subscribe(msgcontainer, 2);

	msgfield = "the publisher send this msg";
	msg = new MsgImp(2,msgfield);

	publisher = new PublisherImp();
	publisher->sendMsg(msgcontainer,msg);

	subscriber2->unsubscribe(msgcontainer,2);

	msgfield = "the publisher send this msg2";
	msg = new MsgImp(2, msgfield);
	publisher = new PublisherImp();
	publisher->sendMsg(msgcontainer, msg);

	return 0;
}


這樣一個訂閱釋出模式就ok了,需要的用的話,直接繼承Subscriber和Publisher就好。

相關推薦

訂閱釋出模式——C++實現

只是自己的一個記錄過程,不做詳細解說 這是這次寫的一個流程 Observer.h #ifndef _OBSERVER_H_ #define _OBSERVER_H_ #include <map> #include <mutex> using

使用MQTT協議的訂閱釋出模式實現從伺服器推送訊息到客戶端功能。

3、手機端設定相同的連線主題引數,訂閱訊息。關鍵程式碼:PC端//伺服器埠 賬號 密碼 private String host = "tcp://127.0.0.1:61613"; private String userName = "admin"; private Stri

springboot結合redis實現redis訂閱釋出模式

redis訂閱釋出模式: Redis提供了釋出訂閱功能,可以用於訊息的傳輸,Redis的釋出訂閱機制包括三個部分,釋出者,訂閱者和Channel。  釋出者和訂閱者都是Redis客戶端,Channel

C++之觀察者模式訂閱-釋出模式

定義: 觀察者模式定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題物件。這個主題物件在狀態發生變化時,會通知所有觀察者物件,使它們能夠自動更新自己。 最常見的一個例子就是:對同一組資料進行統計分析時候,我們希望能夠提供多種形式的表示(例如以表格

Js實現訂閱釋出模式(讓你的程式碼寫得賊六)

簡單例子 var salesoffice = {}; //定義售樓處 salesoffice.clientList = []; //快取列表,存放訂閱者的回撥函式 sale

設計模式C++實現——工廠方法模式

對象 類型 begin 創建對象 dia rate rod rtu log 模式定義: 工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到子類。 模式結構: Creator是一個類,它

大話設計模式C++實現-第17章-適配器模式

req span oid efi cpp endif 對象 adapt sdn 一、UML圖 關鍵詞:Client須要Request()函數,Adaptee提供的是SpecificRequest()函數,Adapter提供一個Request()函數將Ada

HeadFirst設計模式---策略模式 C#實現

模式 adf oid info wing face rmq protected src 鴨子基類 將行為封裝起來 class Duck { protected IFlyBehavior flyBehavior; protec

在 js 中應用 訂閱釋出模式(subscrib/public)

什麼是釋出-訂閱者模式 我們在使用釋出-訂閱者模式之前,先了解什麼是釋出-訂閱者模式。簡單來說,釋出訂閱者模式就是一種一對多的依賴關係。多個訂閱者(一般是註冊的函式)同時監聽同一個資料物件,當這個資料物件發生變化的時候會執行一個釋出事件,通過這個釋出事件會通知到所有的訂閱者,使它

代理模式C++實現

#include <iostream> #include <string&

裝飾模式C++實現

#include <iostream> #include <string> class Person

策略模式模式C++實現

策略模式: 當用戶需要選擇不同的演算法或行為時,如果把這些演算法或行為寫在一個類裡,通過判斷來選擇的話,這個類將變得非常複雜並且難以維護。策略模式就是構造一個抽象類,具體的演算法或者行為繼承這個類,讓使用者來選擇。這樣做的好處是,可以隨時增加或者修改行為,即增加、修改演算法或行為的類就可以了。

簡單工廠模式C++實現

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">面向物件的優點:</span> 1、可維護:修改簡單 2、可複用:

策略模式——C++實現

策略模式其實和簡單工廠模式很相似,在看《大話設計模式》這本書時,一開始也是一度弄混這兩個模式,關於簡單工廠模式的一個介紹以及C++程式碼可以參考上一篇文章點選開啟連結。策略模式和簡單工廠模式最主要的區別在於客戶端使用者需要操作幾個類,下面仍以加、減、乘、除計算來講解: 在上簡單工廠模式中,

觀察者模式訂閱釋出模式)及例項Demo

1、觀察者模式,又稱訂閱釋出模式,其架構如下: 2、例項demo——訂閱天氣,釋出天氣 1>WeatherSubject  目標類 public class WeatherSubject {      priv

RabbitMQ Java 訂閱釋出模式

所有訂閱者都可以獲取到來自交換機轉發的任務訊息 連線到Rabbit,我們都需要一個新的空的佇列,消費者與Rabbit斷開,消費者所接收的那個佇列應該被自動刪除 pom.xml   <project xmlns="http://maven.apache.

大話設計模式C++實現-第3.4.5-設計原則(1)

第三章-單一職責原則 (1).就一個類而言,應該僅有一個引起它變化的原因。 (2)如果一個類承擔的職責過多,就等於把這些職責耦合在了一起,一個職責的變化可能會削弱或者抑制這個類完成其他職責的能力。這種耦合會導致脆弱的設計,當發生變化時,設計會遭受到意想不到的破壞。 (3)軟體設計真正要做

05:原型模式——C++實現

目錄 一、介紹 二、應用場景 三、要點 四、樣例 五、優缺點 一、介紹     原型模式(Prototype Pattern)是用於建立重複的物件,同時又能保證效能。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。

04:工廠模式——C++實現

目錄 一、簡介 二、應用場景 三、要點 四、樣例 五、優缺點 一、簡介 工廠模式(Factory Pattern):定義一個建立物件的介面,讓其子類自己決定例項化哪一個工廠類,工廠模式使其建立過程延遲到子類進行。主要解決介面選擇的問題。此模式的核心思想是封裝類中不

03:建造者模式——C++實現

目錄 一、介紹 二、應用場景 三、要點 四、樣例 五、優缺點 一、介紹 建造者模式(Builder Pattern)使用多個簡單的物件一步一步構建成一個複雜的物件。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。將一個複雜的構建與其表示相分離,使