c++自定义消息管理机制(类似cocos2d-x的实现方式)

       某日写逻辑的时候,突然想到,关于消息管理机制,于是想到cocos2dx的__NotificationCenter,虽然不是写cocos2dx了,但是未尝不可自己写一套类似的消息管理机制,方便通知。

      因此直接借(chao)鉴(xi)它里面的消息管理机制了:


1.Ref基类

      Ref基类的目的是让我需要订阅消息的对象的类继承自他,这样的话我的对象可以通过强转到Ref类型来保存到Notification中,而对于消息中心来说也不用知道订阅消息的对象究竟是哪个类型。

Ref.h:

class Ref
{
public:
	Ref();
	virtual ~Ref();
};

//把子类成员函数的指针当做参数传到观察者用以当做回调函数
//typedef void(Ref::*pdc)();
typedef void (Ref::*SEL_CallFunc)();
typedef void (Ref::*SEL_CallFuncO)(Ref* _ref);

#define CC_CALLFUNC_SELECTOR(_SELECTOR) static_cast<SEL_CallFunc>(&_SELECTOR)
#define CC_CALLFUNCO_SELECTOR(_SELECTOR) static_cast<SEL_CallFuncO>(&_SELECTOR)

#define callfunc_selector(_SELECTOR) CC_CALLFUNC_SELECTOR(_SELECTOR)
#define callfuncO_selector(_SELECTOR) CC_CALLFUNCO_SELECTOR(_SELECTOR)
关于宏定义:宏定义部分其实多次包装,把某个订阅消息的对象成员函数强转成Ref型的函数指针,在发布消息的时候通过该指针调用回调函数,我看cocos2dx中有写好了,就直接拿过来了0.0
Ref.cpp :没什么东西就不贴了
到这里,基类是定义好了,接下来实现观察者对象,即存储订阅消息的对象,以及消息名字,函数指针等一系列的数据信息。

 
 

2.NotificationObserver观察者对象

如下:

class NotificationObserver {
public:
	NotificationObserver(Ref*target, string name, SEL_CallFunc selector)
	{
		m_name = name;
		m_target = target;
		m_selector = selector;
	}
	NotificationObserver(Ref*target, string name, SEL_CallFuncO selector, Ref* _ref)
	{
		m_name = name;
		m_target = target;
		m_Oselector = selector;
	}
	~NotificationObserver(){}
	Ref*getTarget()
	{
		return m_target;
	}
	string GetName()
	{
		return m_name;
	}
	/*SEL_CallFunc getCallBack(){
		return m_selector;
	}*/
	void ObserverCallBack()
	{
		if (m_target)
		{
			(m_target->*m_selector)();
		}
	}
	void ObserverCallBack(Ref* ref)
	{
		if (m_target)
		{
			(m_target->*m_Oselector)(ref);
		}
	}
private:
	Ref*	m_target;
	string	m_name;
	SEL_CallFunc	m_selector ;
	SEL_CallFuncO	m_Oselector;
	//SEL_CallFuncI m_
};
因为东西少,没分cpp了,至于Ref,因为我建文件的时候建立的是类,直接包含cpp,这个是放在NotificationCenter.h了,接下来实现消息派发中心,负责订阅消息,派送消息等功能。


3.NotificationCenter消息管理中心

消息中心必须是单例,在一个程序中只能有一个存在。

NotificationCenter.h

#ifndef __NOTIFICATION_CENTER_
#define __NOTIFICATION_CENTER_

#pragma once
#include"Ref.h"
#include <iostream>
#include<vector>
#include <list>
#include<functional>
using namespace std;

class NotificationObserver;
class NotificationCenter:
{
public:
	NotificationCenter();
	~NotificationCenter();
	static NotificationCenter*getInstance();
	static void destroyInstance();
	//添加观察者
	//被观察的对象,被观察的方法,名字标签
	void addObserver(Ref*target,string name, SEL_CallFunc selector);
	void addObserver(Ref*target, string name, SEL_CallFuncO selector,Ref* _ref);
	//移除观察者
	void removeObserver(Ref*target, string name);
	//清空观察者
	int removeAllObservers(Ref *target);
	//判断该观察者是否已经添加过了
	bool ObserverExisted(Ref *target,string name);

	void PostNotification(string name);

	void PostNotification(string name ,Ref* psender);
private:
	vector<NotificationObserver*>m_array;

};

class NotificationObserver :
{
public:
	NotificationObserver(Ref*target, string name, SEL_CallFunc selector)
	{
		m_name = name;
		m_target = target;
		m_selector = selector;
	}
	NotificationObserver(Ref*target, string name, SEL_CallFuncO selector, Ref* _ref)
	{
		m_name = name;
		m_target = target;
		m_Oselector = selector;
	}
	~NotificationObserver(){}
	Ref*getTarget()
	{
		return m_target;
	}
	string GetName()
	{
		return m_name;
	}
	/*SEL_CallFunc getCallBack(){
		return m_selector;
	}*/
	void ObserverCallBack()
	{
		if (m_target)
		{
			(m_target->*m_selector)();
		}
	}
	void ObserverCallBack(Ref* ref)
	{
		if (m_target)
		{
			(m_target->*m_Oselector)(ref);
		}
	}
private:
	Ref*	m_target;
	string	m_name;
	SEL_CallFunc	m_selector ;
	SEL_CallFuncO	m_Oselector;
	//SEL_CallFuncI m_
};
#endif

NotificationCenter.cpp

</pre><pre name="code" class="cpp">#include "stdafx.h"

#include "NotificationCenter.h"


static NotificationCenter *_notification = nullptr;
NotificationCenter::NotificationCenter()
{
	m_array.clear();
}
NotificationCenter::~NotificationCenter()
{
}
NotificationCenter*NotificationCenter::getInstance()
{
	if (_notification != nullptr)
	{
		return _notification;
	}
	_notification = new NotificationCenter;
	return _notification;
}

void NotificationCenter::destroyInstance()
{
	if(_notification!=nullptr)
	delete _notification;
}

bool NotificationCenter::ObserverExisted(Ref *target, string name)
{
	NotificationObserver *obj = nullptr;
	for each (obj in m_array)
	{
		if (!obj)
		{
			continue;
		}
		
		if (obj->getTarget()==target && obj->GetName()==name)
		{
			return true;
		}
	}
	return false;
}
void NotificationCenter::addObserver(Ref*target, string name, SEL_CallFunc selector)
{
	
	if (this->ObserverExisted(target, name))
	{
		return;
	}
	NotificationObserver *observe = new NotificationObserver(target, name, selector);
	m_array.push_back(observe);
}
//带参数的
void NotificationCenter::addObserver(Ref*target, string name, SEL_CallFuncO selector, Ref* _ref)
{

	if (this->ObserverExisted(target, name))
	{
		return;
	}
	Ref* ref = new Ref();
	NotificationObserver *observe = new NotificationObserver(target, name, selector,_ref);
	//std::function<void()> func = std::bind(&Ref::update, ref);
	//NotificationObserver *observe = new NotificationObserver(std::bind(&Ref::update, ref), name, selector);
	m_array.push_back(observe);
}
void NotificationCenter::removeObserver(Ref*target, string name)
{
	//vector<NotificationObserver*>::iterator itor;
	auto itor = m_array.begin();
	int i = 0;
	for (itor = m_array.begin(); itor != m_array.end();)
	{
		if ((*itor)->getTarget() == target && ((*itor)->GetName() == name))
		{
			//delete m_array.at(i);
			delete *itor;
			itor = m_array.erase(itor);
		}
		else{
			i++;
			itor++;
		}
	}
}
int NotificationCenter::removeAllObservers(Ref*target)
{
	vector<NotificationObserver*>::iterator itor;
	itor = m_array.begin();
	for (itor = m_array.begin(); itor != m_array.end();)
	{
		if (((NotificationObserver*)*itor)->getTarget()== target)
		{
			delete *itor;
			//delete m_array.at(i);
			itor=m_array.erase(itor);
		}
		else{
			itor++;
		}
	}
	return 0;
}


void NotificationCenter::PostNotification(string name, Ref* psender)
{
	for (auto sp : m_array)
	{
		if (sp->GetName() == name)
		{
			sp->ObserverCallBack(psender);
		}
	}
}

void NotificationCenter::PostNotification(string name)
{
	for (auto sp:m_array)
	{
		if (sp->GetName()==name)
		{
			sp->ObserverCallBack();
		}
	}
}

 
至此,消息管理系统已然完善,代码简单就没一一注释了。
4. Test测试样例
系统实现了,接下来就是测试了,首先class一个Sprite类,继承自Ref基类:
Sprite.h:
#ifndef _SPRITE_H_
#define _SPRITE_H_
#pragma once

#include "Ref.h"
using namespace std;

class Sprite :public Ref, Blog
{
public:
	
	Sprite();
	~Sprite();
	 void test();
	 void dosomthing();
};

#endif

Sprite.cpp:
#include "Sprite.h"
#include <iostream>
#include"NotificationCenter.h"

Sprite::Sprite()
{
}


Sprite::~Sprite()
{
}
void Sprite::test()
{
	
	cout << "I am here"<<endl;
	this->dosomthing();
}
void Sprite::dosomthing()
{
	printf("I am here to doing somthing");
	return;
}

接着main函数:
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include<unordered_map>
#include<map>
#include<set>
#include"Sprite.h"
#include"NotificationCenter.h"
using namespace std;
void MainTest()
{
	auto sprite=new Sprite();
	NotificationCenter::getInstance()->addObserver(dynamic_cast<Ref*>(sprite), "test", callfunc_selector(Sprite::test));
	NotificationCenter::getInstance()->PostNotification("test");
	delete sprite;
}

int _tmain(int argc, _TCHAR* argv[])
{
	MainTest();
	return 0;
}



运行图:

附:同事吐槽我的这个机制,Ref基类完全是没有任何意义的基类,仅仅只作为强转对象的目标类,还有什么没必要啥的,真是饱受诟病,其实我当时也只是想Ref都借(chao)鉴(xi)了,似乎可以把他们的内存管理机制也抄过来,所以当时是觉得Ref是可以继续拓展功能的,然则发现bug之后,没有去使用这个方式了,请移步下一篇升级版。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值