某日寫邏輯的時候,突然想到,關於消息管理機制,於是想到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
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();
}
}
}
#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;
}
運行圖: