表驱动--用于在复杂消息分发中,取代if/else和switch/case结构

来源:互联网 发布:wildfly 端口配置 编辑:程序博客网 时间:2024/06/05 04:44

在开发过程中,经常遇到需要在不同的场景下调用不同的函数以实现不同的功能(例如消息分发),传统的设计方法中大量的使用 if/else,switch/case结构,如下所示:

int dispatch_func(unsigned msg_id, void* p_msg, int  msg_len)   {    int result;    switch (msg_id)    {    case MSG_A:        result = f_a(p_msg,mgs_len);        break;    case MSG_B:        result = f_b(p_msg,msg_len);        break;    case MSG_C:        result = f_c(p_msg,msg_len);        break;    //...    default:        puts("The msg_id is not defined!");        break;    }    return result;}int f_a(void* p_msg, int msg_len){...}int f_b(void* p_msg, int msg_len){...}int f_c(void* p_msg, int msg_len){...}

很明显,上面这种实现方式,分支越多,可读性越差,维护起来也越麻烦。下面使用表驱动的方式对代码进行重新规划:

#define MSG_BEGIN   0x123#define MSG_A       MSG_BEGIN+1#define MSG_B       MSG_BEGIN+2#define MSG_C       MSG_BEGIN+3#define MSG_MAX     MSG_BEGIN+4typedef int (*msg_func)(unsigned msg_id, void* p_msg, int msg_len);msg_func dispatch_table[]={     f_a,     f_b,     f_c};int dispatch_func(unsigned msg_id, void* p_msg, int msg_len){        if(( msg_id >= MSG_A) && ( msg_id < MSG_MAX))            return dispatch_table[msg_id-MSG_A](p_msg,msg_len);        else            return -1;}

如果msg_id为不连续的,不能直接找到其处理函数,就要从数组中查找出其处理函数,如下:

#define MSG_BEGIN   0x123#define MSG_A       MSG_BEGIN+1#define MSG_B       MSG_BEGIN+2#define MSG_C       MSG_BEGIN+3#define MSG_MAX     MSG_BEGIN+4typedef int (*msg_func)(unsigned msg_id, void* p_msg, int msg_len);typedef struct {     unsigned msg_id;     msg_func func;}dispatch_item;dispatch_item dispatch_table[]={    /*这里假定这三个消息不是连续存放的*/   {MSG_A,f_a},    //...   {MSG_B,f_b},    //...   {MSG_C,f_c}};int max_items=sizeof(dispatch_table)/sizeof(dispatch_table[0]);int dispatch_func(unsigned msg_id, void* p_msg, int msg_len){    int i;    for (i=0; i<max_items; i++)    {        if (function_no == dispatch_table[i].msg_id)            return dispatch_table[i].func(p_msg, msg_len);    }    return -1;}

还可以使用哈希表设计表驱动,这样对于不连续的消息,也能快速查找到其处理函数:

#define MSG_BEGIN   0x123#define MSG_A       MSG_BEGIN+1#define MSG_B       MSG_BEGIN+2#define MSG_C       MSG_BEGIN+3#define MSG_MAX     MSG_BEGIN+4typedef int (*msg_func)(unsigned msg_id, void* p_msg, int msg_len);typedef std::hash_map<unsigned , msg_func> MsgHandlerMap;MsgHandlerMap HandlerMap;void InitHandlerMap(){        HandlerMap[MSG_A] = reinterpret_cast<ProcessFuncPtr>(&f_a);        HandlerMap[MSG_B] = reinterpret_cast<ProcessFuncPtr>(&f_b);        HandlerMap[MSG_C] = reinterpret_cast<ProcessFuncPtr>(&f_c);        //...}int ProcessControl(unsigned msg_id, void* p_msg, int msg_len){    CmdHandlerMap::iterator it = HandlerMap.find(msg_id);    if (it != HandlerMap.end())    {        ProcessFuncPtr pHandler = it->second;        return pHandler(p_msg, msg_len);    }    return -1;}

表驱动是C语言设计利器,搭配函数指针,威力无穷。 



0 0