単純な観察者モードの実現cocos 2 dx


ヘッダファイル
//   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);
		}
	}
}