一个用C++实现的Dispatcher(二)
遗留代码就是遗留代码,总会有一些让人意想不到的地方,原以为所有消息都是由一个类(MsgHandler)处理的,可事实上,不是。
if (msg->id == "open") {
MsgHandler handler(msg);
handler.open();
} else if (msg->id == "close") {
MsgHandler2 handler(msg);
handler.close();
} else if (…) {
…
} else {
// exception handler
…
}
上面的代码里面只有消息处理类的名字不同,其它的处理完全相同。不过,这样就让之前那个dispatcher就显得势单力薄。解决程序设计的问题,有一个很好用的处理手法:加个间接层。于是,
class DispatchHandler {
public:
virtual void execute(Msg* msg) = 0;
};
对于前面的两种类型,道理上来说,我们需要分别为两个类型(MsgHandler和MsgHandler2)分别编写对应的子类。不过,我们用的是C++,是的,模板:
template<typename T>
class DispatchHandlerImpl : public DispatchHandler {
typedef void (T::*Func)();
public:
DispatchHandlerImpl(Func sourceHandler)
:handler(sourceHandler) {}
void execute(Msg* msg) {
T msgHandler(msg);
(msgHandler.*(this->handler))();
}
private:
Func handler;
};
原来的dispatcher也要相应的调整:
#include <map>
class MsgDispatcher {
public:
...
void dispatch(Msg* msg);
private:
std::map<string, DispatchHandler> handlers;
};
void MsgDispatcher::dispatch(Msg* msg) {
DispatchHandler* handler = this->handlers[msg->id];
if (handler) {
handler->execute(msg);
} else {
// exception handler
…
}
}
对应的注册代码也就变成:
handlers["open"] = new DispatchHandlerImpl<MsgHandler>(&MsgHandler::open);
handlers["close"] = new DispatchHandlerImpl<MsgHandler2>(&MsgHandler2::close);
有代码洁癖的我们发现类名在这里重复了,于是,定义一个宏对其进行简化:
#define DISPATCH_HANDLER(className, funcName) \
DispatchHandlerImpl <className>(&className::funcName)
handlers["open"] = new DISPATCH_HANDLER(MsgHandler, open);
handlers["close"] = new DISPATCH_HANDLER(MsgHandler2, close);