1 回调管理器
利用上面的技术可以实现一个回调管理器,使用这个东西可以使互相关联的模块解耦。
1.1 代码示例
typedef CCallbackManager<std::string> CallbackManager;
CallbackManager manager;
void Test0()
{
int a = 9;
}
void Test1(int i)
{
int a = 9;
}
Struct xyz
{
Int Menberfunc(bool);
};
Xyz *p = new xyz;
manager.RegisterCallback("msg0",CreateCallback(Test0));
manager.RegisterCallback("msg1",CreateCallback(Test1));
manager.RegisterCallback("msg2",CreateCallback(p,&Xyz ::Menberfunc));
manager.ExecCallback("msg0");
manager.ExecCallback("msg1",3);
manager.ExecCallback("msg2",false);
1.2 实现
实现一个回调管理器很简单,但是如果考虑到void*类型的回调就相当的麻烦,再考虑到回调的执行线程就更加麻烦,先来看回调管理器的声明:
template<class MSG,class Method = CallbackFunc *,class Exec = CDirectExec
,template<class> class Deleter = CallbackDeleter>
class CCallbackManager
{
private:
typedef typename std::map<MSG,std::vector<Method> >::iterator iterType;
typedef typename std::vector<Method>::size_type sizeType;
public:
CCallbackManager(){}
~CCallbackManager(){Clear();}
void Clear()
{
exec.Clear();
for(iterType it = m_callbacks.begin();it!=m_callbacks.end();++it)
{
std::vector<Method> &callback = it->second;
for( sizeType i = 0;i<callback.size();++i)
{
Deleter<Method>::Delete(callback[i]);
}
}
m_callbacks.clear();
}
void RegisterCallback(MSG msg,Method m){m_callbacks[msg].push_back(m);}
template<class T1,class T2,class T3>
void ExecCallback(MSG msg,TRAITS(T1) t1,TRAITS(T2) t2,TRAITS(T3) t3)
{
std::vector<Method> &callbacks = m_callbacks[msg];
for(sizeType i = 0;i<callbacks.size();++i)
{
exec.Execute(callbacks[i],t1,t2,t3);
}
}
private:
Exec exec;
std::map<MSG,std::vector<Method> > m_callbacks;
};
这里只给出了3个参数的回调调用方法,详细代码可参考附录,第一个模板参数是MSG,这是消息的类型,可以是int, string或其他可比较的类型,第二个参数是回调方法,可以是CallbackFunc *或void*,第三个参数是回调执行器,用来实现直接回调或线程回调,第四个参数是回调释放器,加入这个是由于释放行为对于CallbackFunc *和void*是不同的。
CDirectExec的实现:
class CDirectExec
{
public:
void Execute(CallbackFunc *p)
{
p->Excute();
}
template<class T1>
void Execute(CallbackFunc *p,T1 &t1)
{
ExcuteCallback(p,t1);
}
template<class T1,class T2>
void Execute(CallbackFunc *p,T1 &t1,T2 &t2)
{
ExcuteCallback(p,t1,t2);
}
template<class T1,class T2,class T3>
void Execute(CallbackFunc *p,T1 &t1,T2 &t2,T3 &t3)
{
ExcuteCallback(p,t1,t2,t3);
}
template<class T1,class T2,class T3,class T4>
void Execute(CallbackFunc *p,T1 &t1,T2 &t2,T3 &t3,T4 &t4)
{
ExcuteCallback(p,t1,t2,t3,t4);
}
template<class T1,class T2,class T3,class T4,class T5>
void Execute(CallbackFunc *p,T1 &t1,T2 &t2,T3 &t3,T4 &t4,T5 &t5)
{
ExcuteCallback(p,t1,t2,t3,t4,t5);
}
void Clear() {}
void Remove(CallbackFunc *p) {}
};
通过线程来实现回调的类需要你自己实现,只要提供和CDirectExec相同的接口皆可。
假设你自己实现了一个通过线程队列来执行回调的类CThreadExec,那么你可以这么定义一个使用线程的回调管理器:
typedef CCallbackManager<int,CallbackFunc*,CThreadExec> CallbackManager;
如果对代码有兴趣的人可以到我上传的资源里找。