头文件
// 王智泉 2012/06/11
#ifndef __myNotification__H__
#define __myNotification__H__
#include "CCPlatformMacros.h"
#include <vector>
#include <map>
#include <string>
// 回调
class myNotification;
class myCallbackBase
{
public:
myCallbackBase(){}
virtual bool operator()(const myNotification& notification) = 0;
};
template<typename T>
class myMemberCallback : public myCallbackBase
{
public:
typedef bool(T::*CallBackFun)(const myNotification&);
myMemberCallback(CallBackFun func, T* target)
: _function(func)
, _target(target){}
virtual bool operator()(const myNotification& notification)
{
return (_target->*_function)(notification);
}
private:
CallBackFun _function;
T* _target;
};
// 观察者
class CC_DLL myObserver
{
public:
myObserver():_target(NULL) , _callback(NULL), _count(NULL){}
template<typename T>
myObserver(T* target, bool (T::*function)(const myNotification&))
: _callback(new myMemberCallback<T>(function, target))
, _count(new int(1))
, _target(target)
{
}
myObserver(const myObserver& other)
{
this->_count = other._count;
this->_callback = other._callback;
this->_target = other._target;
(*this->_count)++;
}
virtual ~myObserver()
{
if (_count)
{
if (--*_count == 0)
{
if (_callback)
{
delete _callback;
_callback = NULL;
}
delete _count;
_count = NULL;
}
}
}
virtual bool operator()(const myNotification& notification)
{
return (*_callback)(notification);
}
virtual bool operator()(myObserver* other)
{
return _target == other->_target;
}
virtual myObserver& operator=(const myObserver& other)
{
if (_count)
{
if (--*_count == 0)
{
if (_callback)
{
delete _callback;
_callback = NULL;
}
delete _count;
_count = NULL;
}
}
this->_count = other._count;
this->_callback = other._callback;
this->_target = other._target;
(*this->_count)++;
return *this;
}
const void* getTarget() const
{ return _target; }
private:
int* _count; // 引用次数
myCallbackBase* _callback;
void* _target;
};
// 观察者查找器
class myObjserverFinder
{
public:
myObjserverFinder(void* target) :_target(target){}
~myObjserverFinder()
{
}
bool operator()(const myObserver & obs)
{
return _target == obs.getTarget();
}
private:
void* _target;
};
// 事件参数
class CC_DLL myNotification
{
public:
myNotification(void* sender, void* arg):_sender(sender), _arg(arg) {}
void* _sender;
void* _arg;
std::map<std::string, void*> _userDatas;
};
// 事件中心
class CC_DLL myNotificationCenter
{
public:
virtual ~myNotificationCenter();
static myNotificationCenter* defaultNotification()
{
static myNotificationCenter instance;
return &instance;
}
// 添加观察者
void addObserver( const char* eventName, const myObserver& observer);
// 删除观察者
void removeObserver(const char* eventName, void* target);
// 发送消息
void postNotification(const char* eventName, const myNotification& notification);
private:
typedef std::vector<myObserver> ObserverList;
typedef std::map<std::string, ObserverList*> EventList;
EventList _eventList;
};
#endif
CPP
// 王智泉 2012/06/11
#include "myNotification.h"
#include "ccMacros.h"
#include <algorithm>
using namespace cocos2d;
// =================================================================================================
myNotificationCenter::~myNotificationCenter()
{
for (EventList::iterator epos = _eventList.begin(); epos != _eventList.end(); ++epos)
{
ObserverList* observers = epos->second;
delete observers;
}
_eventList.clear();
}
// =================================================================================================
void myNotificationCenter::addObserver( const char* eventName, const myObserver& observer)
{
CCAssert(NULL != eventName, "add observer error1");
ObserverList* observerList = NULL;
EventList::iterator ePos = _eventList.find(eventName);
if (ePos != _eventList.end())
{
observerList = ePos->second;
} else
{
observerList = new ObserverList;
_eventList[eventName] = observerList;
}
observerList->push_back(observer);
}
// ================================================================================================
void myNotificationCenter::removeObserver(const char* eventName, void* target)
{
EventList::iterator ePos = _eventList.find(eventName);
if (ePos != _eventList.end())
{
ObserverList* observers = ePos->second;
std::remove_if(observers->begin(), observers->end(), myObjserverFinder(target));
if (observers->size() == 0)
{
delete observers;
_eventList.erase(ePos);
}
}
}
// ================================================================================================
void myNotificationCenter::postNotification(const char* eventName, const myNotification& notification)
{
EventList::iterator epos = _eventList.find(eventName);
if (epos != _eventList.end())
{
ObserverList* observers = epos->second;
for (ObserverList::iterator opos = observers->begin(); opos != observers->end(); ++opos)
{
(*opos)(notification);
}
}
}