• 一个简单观察者模式的实现 cocos2dx


    头文件

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


  • 相关阅读:
    【Linux】Gitlab库已损坏前端显示500错误解决方法
    【linux】gitlab 的安装以及数据迁移
    【PHP】图片转换为base64,经过post传输后‘+’会变成 ‘空格’
    【Mac】解决外接显示器时无法用键盘调节音量
    【Mac】 /usr/local 文件夹权限问题
    学妹问的Spring Bean常用配置,我用最通俗易懂的讲解让她学会了
    上海月薪 1w 和家乡月薪 5000 你选择哪?
    30岁码农的一次面试经历:不委屈自己
    写4条宝贵的经验,给初入职场的你
    Java 8 Optional 良心指南,建议收藏
  • 原文地址:https://www.cnblogs.com/iapp/p/3631786.html
Copyright © 2020-2023  润新知