Normal
0
7.8 磅
0
2
false
false
false
EN-US
ZH-CN
X-NONE
又和一个团队合作,面前又摆着一堆分发的代码,不同的是,这次用的是C++:
if (msg->id == "open") {
MsgHandler handler(msg);
handler.open();
} else if (msg->id == "close") {
MsgHandler handler(msg);
handler.close();
} else if (…) {
…
} else {
// exception handler
…
}
不要问我为什么不是每个消息对应一种处理类,要是知道为什么,就不是遗留代码了。于是,我们尝试着用C++写了一个dispatcher。下面是这个dispatcher的声明:
#include 因为要处理遗留代码,这里用到了指向成员函数的指针,也就提高了理解这段代码的门槛。具体实现如下:
void MsgDispatcher::dispatch(Msg* msg) {
handlerFunc func = this->handlers[msg->id];
if (func) {
MsgHandler msgHandler(pkg);
(msgHandler.*func)();
} else {
// exception handler
…
}
}
注册很简单:
handlers["open"] = &MsgHandler::open;
handlers["close"] = &MsgHandler::close;
遗留代码就是遗留代码,总会有一些让人意想不到的地方,原以为所有消息都是由一个类(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
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 对应的注册代码也就变成:
handlers["open"] = new
DispatchHandlerImpl(&MsgHandler::open);
handlers["close"] = new
DispatchHandlerImpl(&MsgHandler2::close);
有代码洁癖的我们发现类名在这里重复了,于是,定义一个宏对其进行简化:
#define DISPATCH_HANDLER(className, funcName) \
DispatchHandlerImpl (&className::funcName)
handlers["open"] = new DISPATCH_HANDLER(MsgHandler, open);
handlers["close"] = new DISPATCH_HANDLER(MsgHandler2, close);
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12925485/viewspace-694497/,如需转载,请注明出处,否则将追究法律责任。