某日写逻辑的时候,突然想到,关于消息管理机制,于是想到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();
}
}
}
至此,消息管理系统已然完善,代码简单就没一一注释了。
系统实现了,接下来就是测试了,首先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之后,没有去使用这个方式了,请移步下一篇升级版。