消除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、所有消息處理類都要繼承自一個接口,這樣在分配函數中,才能統一的調用消息處理方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章