消除switch/case语句,不破坏代码的封闭性,使程序结构更符合面向对象思想(一)

一、引入:最近在学习一个执行体库的封装,里面线程间的通信使用的是基于消息循环机制的消息通信。

稍微讲下这套通信机制的封装:线程A拥有一个消息队列queue,其他的线程B、C、D...如果想要和线程A通信,就可以向queue中放消息。显然该队列是一个生产者/消费者模型(单读多写)。

二、回到主题:好,现在开始考虑:线程A需要处理多种消息类型,而每种消息类型的处理方式可能不同,问题的解决方法最简单的就是使用switch/case语句

switch(msg)

{

  case msgB:

     。。

  case msgC:

     。。

  case msgD:

    。。

}

但是,当我们的程序需要增加新的消息时,就需要在switch/case 结构中添加新的case语句,这显然就破坏了代码的封闭性,不符合面向对象的思想。


三、用面向对象的方法消除switch/case :

思路:

1、维护一个消息管理器,实际上就是一张2维表,表中的一条记录表示:消息B对应的处理对象MsgBProcessor * pBPro;

2、对外,我们提供表的注册方法(添加一种消息类型和其对应的处理对象):Rigister

来看一个具体实现:

1、2维表的使用

std::map<unsigned long MsgTypeId,MessageProcessor *> messageMappingTable;
DispatchMessage(Message * pMsg)
{
  std::map<unsigned long MsgTypeID, MessageProcessor *>::iterator it;
  it = messageMappingTable.find(pMsg->MsgTypeID);
  if(it->second != 0)
  {
    it->second->Notify(pMsg); //Notify()就是不同消息的处理对象处理消息业务逻辑的具体实现
  }
}

注意:所有的消息处理对象必须要继承自一个接口,并且在该接口中要提供一个统一的消息处理业务逻辑的入口Notify(pMsg)

2、2维表的注册:

Rigister(unsigned long MsgTypeId, MessageProcessor * pMsgPro)
{
  messageMappingTable[MsgTypeId] = pMsgPro;
}

总结,消除switch/case方法实现的要点:

1、在分配消息之前,将消息的类型ID和处理此类消息的对象注册到消息管理器中

2、接受到消息并准备分配消息的时候,首先根据消息类型的ID号去消息管理器中查找处理处理对象

3、所有消息处理类都要继承自一个接口,这样在分配函数中,才能统一的调用消息处理方法

你可能感兴趣的:(消除switch/case语句,不破坏代码的封闭性,使程序结构更符合面向对象思想(一))