头文件
// 王智泉 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); } } }