1. 程式人生 > >使用std::function和std::bind寫的觀察者模式

使用std::function和std::bind寫的觀察者模式

最近由於學cocos2d-x3.2,看到其中的回撥函式使用了std::bind,發現這是一個挺有趣的東西,它可以繫結一個函式,甚至一個函式物件,生成一個綁定了函式引數的函式物件,所以嘗試用它寫了一下觀察者模式。

首先是觀察者單例:

Ref是模仿cocos2d-x寫的一個包含最基礎引用計數的基類。

.h檔案

#include "Singleton.h"
#include "Ref.h"
#include "RefManage.h"
#include <functional>

/**
*	訊息管理(單例,嘗試實現類似cocos2d-x觀察者模式)
*/
class Notification :public Singleton<Notification>
{
public:
	//發出訊息
	void postMessage(const std::string& msg,Ref* data);
	//新增觀察者
	void addObserver(Ref* target,std::function<void(Ref*)> fun,const std::string& msg);
	//刪除觀察者
	bool removeObserver(Ref* ref,const std::string& msg);
	//訊息派發
	void dispatchMsg();

public:
	struct ObserverStr
	{
		Ref* _ref;				//觀察者物件
		std::function<void(Ref*)> _fun;		//繫結的類成員函式
		std::string _msg;			//監聽的訊息
	};
	struct MsgStr
	{
		std::string _msg;			//發出的訊息
		Ref* _data;				//附帶的資料
	};
private:
	Notification(void);
	~Notification(void);

	friend Singleton<Notification>;
	friend std::auto_ptr<Notification>;

private:
	std::vector<ObserverStr> m_observerVector;	//觀察者列表
	std::vector<MsgStr>	m_msgVector;		//訊息列表
};

.cpp

#include "Notification.h"

Notification::Notification(void)
{
	m_observerVector.clear();
}

Notification::~Notification(void)
{
	m_observerVector.clear();
}

void Notification::postMessage( const std::string& msg,Ref* data )
{
	MsgStr msgstr = {msg,data};
	m_msgVector.push_back(msgstr);
}

void Notification::addObserver( Ref* target,std::function<void(Ref*)> fun,const std::string& msg )
{
	ObserverStr obstr = {target,fun,msg};
	m_observerVector.push_back(obstr);
}

bool Notification::removeObserver( Ref* ref,const std::string& msg )
{

	for (auto it = m_observerVector.begin();it!=m_observerVector.end();++it)
	{
		if ((*it)._ref == ref && (*it)._msg.compare(msg)==0)
		{
			m_observerVector.erase(it);
			return true;
		}
	}
	return false;
}

void Notification::dispatchMsg()
{
	for (auto i = m_msgVector.begin();i!=m_msgVector.end();)
	{
		bool isErase = false;
		for (auto j = m_observerVector.begin();j!=m_observerVector.end();++j)
		{
			if ((*i)._msg.compare((*j)._msg) == 0)
			{
				((*j)._fun)((*i)._data);<span style="white-space:pre">	</span>//這是呼叫繫結的成員函式
				i = m_msgVector.erase(i);
				isErase = true;
			}
		}
		if(!isErase)
			++i;
	}
}

測試類AB:
class ChildA : public Ref
{
public:
	ChildA(){}
	~ChildA(){};
	void postmsg(MyString* str){
		Notification::getInstance()->postMessage("child",str);}
};

class ChildB :public Ref
{
public:
	ChildB(){}
	void printdata(Ref* data)	{
		MyString* str = (MyString*)data;
		std::cout<<(str->m_str)<<std::endl;
	}
};

//用於傳遞的Data,也要繼承Ref
class MyString :public Ref
{
public:
	MyString(const std::string& str)
		{m_str = str;}

	std::string m_str;
};

主函式測試:

ChildA* p = new ChildA;
ChildB* q = new ChildB;

//新增觀察者
Notification::getInstance()->addObserver(q,std::bind(&ChildB::printdata,q,std::placeholders::_1),"child");
//傳送訊息
MyString* str = new MyString("data");
p->postmsg(str);
上面addObserver時用了std::bind繫結ChildB的成員函式,這個函式接收一個引數,這裡用的std::placeholders::_1是佔位符,用來預留了引數的位置,_1指的是通過bind後的函式呼叫時第一個引數繫結到原函式的第一個引數位置。

最後訊息迴圈中迴圈呼叫來派發訊息:

Notification::getInstance()->dispatchMsg();

從而通過bind的函式呼叫實現通知的效果。

測試結束時應該remove觀察者。

測試結果:

使用std::function和std::bind似乎可以實現許多耦合度較低的設計模式,這裡只是嘗試一下。


寫得不好,歡迎指正。


相關推薦

使用std::functionstd::bind觀察模式

最近由於學cocos2d-x3.2,看到其中的回撥函式使用了std::bind,發現這是一個挺有趣的東西,它可以繫結一個函式,甚至一個函式物件,生成一個綁定了函式引數的函式物件,所以嘗試用它寫了一下觀察者模式。 首先是觀察者單例: Ref是模仿cocos2d-x寫的一個包

C++11之std::functionstd::bind

std::function是可呼叫物件的包裝器,它最重要的功能是實現延時呼叫: #include "stdafx.h" #include<iostream>// std::cout #include<functional>// std::fu

C++11 中std::functionstd::bind的用法

關於std::function 的用法: 其實就可以理解成函式指標 1. 儲存自由函式 void printA(int a) { cout<<a<<endl; } std::function<void(int a)

關於std::functionstd::bind繫結成員函式

關於std::bind繫結成員函式與虛擬函式的方法。 #include <iostream> #include <functional> using namespace std; class A { public:     A() :m_a(0)

C++11新特性應用--實現延時求值(std::functionstd::bind)

說是延時求值,注意還是想搞一搞std::function和std::bind。 現在就算是補充吧,再把std::bind進行討論討論。 何為Callable Objects? 即可呼叫物件,比如函式指標、仿函式、類成員函式指標等都可稱為可呼叫物件。

使用std::functionstd::bind實現區域性函式做回撥

昨日的求教得到了大家的熱烈迴應,除了要我解釋友圈封面之外,也有很多牛人給了很棒的指導意見,其中最為有效的是說使用std::function加std::bind,今晚我就實驗一下.          這兩個東西是c++11的東西,std::function,抄襲別人的理解就是

C++11 std::functionstd::bind繫結器

前言 C++11增加了std::function和std::bind,使得使用標準庫函式時變得方便,而且還能方便地實現延遲求值。C++中,存在“可呼叫物件”這麼一個概念。準確來說,可呼叫物件有如下的定

structclass的區別 觀察模式 https連線 點選button收到點選事件,中間發生了什麼

提示:英文原文寫於2009年,當時的Firefox和最新版的Firefox,介面也有很大改動。以下是正文。 花了數小時閱讀了如潮的好評,Bob最終迫不及待為他購買的托斯卡納全脂牛奶點選了“進行結算”,然後…… 哇!剛剛發生了什麼? 在點選按鈕過後的220毫秒時間內,發生了一系

C++中的仿函式,std::functionbind()的用法

1.仿函式:又叫std::function,是C++中的一個模板類 2.C語言中的函式指標: int  add(int a,int b) {   return a+b; } typedef int (*func)(int,int);//給函式型別定義別名

《深入應用C++11》筆記-std::functionbind

接下來的內容將會補充在《深入理解C++11》書中沒有涉及的一些比較常用的特性,內容取自《深入應用C++11》。 在C++中,存在“可呼叫物件(Callable Objects)”這麼一個概念。準確來說,可呼叫物件有如下幾種定義: 是一個函式指標。 是一

std::functionstd::bind 函式指標

function模板類和bind模板函式,使用它們可以實現類似函式指標的功能,但卻卻比函式指標更加靈活,特別是函式指向類 的非靜態成員函式時。 std::function可以繫結到全域性函式/類靜態成員函式(類靜態成員函式與全域性函式沒有區別),如果要繫結到類的非靜態成

觀察模式發布/訂閱模式的區別

observe nbsp 初步 有時 觀察 觀察者 發生 狀態 發現 在事件總線(EventBus)的架構設計中,用到了發布/訂閱模式,但發現和觀察者模式挺接近,有時容易發生混淆,現試圖分清一下他們的關系。 觀察者模式的角色為觀察者(observer)

實戰c++中的vector系列--對vector&lt;自己定義類&gt;使用std::find std::find_if 算法

++ pac price key fadein 輸出 var getitem mod 之前博客講了一些關於std::find和std::find_ if的一些使用方法。可是沒有講述對於vector中存儲的是自己定義的類。那麽怎麽樣使用std::find和

使用util包裏自帶的接口類實現觀察模式

註意 簡化 響應 cat pan hang sys ext main 之前的關於觀察者模式的文章,是用自己寫的Observable接口和Observer接口,然後進行實現。其實官方的util包下自帶有實現觀察者模式對應的接口和類,可以簡化我們的代碼結構。 比如我們可

基於std::mutex std::lock_guard std::condition_variable std::async實現的簡單同步隊列

有關 com urn list 占用空間 當前 條件變量 size 多線程 C++多線程編程中通常會對共享的數據進行寫保護,以防止多線程在對共享數據成員進行讀寫時造成資源爭搶導致程序出現未定義的行為。通常的做法是在修改共享數據成員的時候進行加鎖--mutex。在使用鎖的時

模板方法模式 + 觀察模式 + 簡單工廠模式 + 單例模式實現一個簡單的數據表讀

private 數據庫鏈 obs imp 通知 model 數據表 ring pri 實現功能: 對數據表的讀要緩存起來,對數據表的寫需要清除緩存. 數據表根據屬性字段來決定是否緩存 可以更換數據庫鏈接方式,比如可以隨時更換為mysql或mysqli() 當插入數據時給出一

PHP 觀察模式php實現 Observer Pattern

BE pattern 修改 private ray 擴展 UNC array type 觀察者模式:  觀察者模式(Observer Pattern):定義對象間的一種一對多依賴關系,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。觀察者模式又叫做發布

觀察模式發布訂閱模式(上)

nts 針對 處理 nds script 分享圖片 .data cto 這樣的 觀察者模式 定義:觀察者模式(Observer Pattern):定義對象間的一種一對多依賴關系,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。 其中有兩個定義需要明確,

中介模式觀察模式區別?

observer server serve 有一個 obs 交互 進行 強調 一個 中介者(mediator)強調的是同事(colleague)類之間的交互 而觀察者(observer)中的目標類(subject)強調是目標改變後對觀察者進行統一的通訊 兩者非常相同的一點就

微信訂閱號的關註消息推送中的觀察模式

obs 取消 account bstr ans 定義 bubuko ros 17.     觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象,主體對象的狀態變化會通知所有觀察者對象。觀察者模式又叫做發布-訂閱模式、模型-視圖模式、源-監聽器模式