模式之消息树
消息樹,并不是公認的設計模式之一,是本人根據觀察者模式發展來的,并于軟件實踐中得以廣泛應用,已經是本人的支柱編碼結構。
觀察者模式是觀察者、被觀察者,兩者有從屬關系,被觀察者主動改變,通知觀察者。并且在觀察者更新的時候也有不方便的地方(見模式之觀察者模式)。下面是筆者設計的消息樹:
消息樹分兩部分,消息和消息節點。消息節點可以組成樹狀結構(消息節點有父子關系:一父多子)。消息就在消息樹上跑。由于面向對象編程的編程方式,很自然的會形成很多樹狀結構的東西,而且,為了方便協調需要通信。消息樹建立了一個樹狀通信通道,任意節點都是消息的發起位置,也是消息的處理位置,消息在樹上有兩種流動模式,向上即向根節點流動是單條流動路線,向下即向葉子節點流動是廣播,廣播節點以下都能收到消息。消息發出后沿樹流動直到有節點處理后返回,這種發消息,處理消息可以是消息樹的若干級之間。對于一個節點,它發消息,不用管誰處理,只要明白向父節點發還是廣播給子節點,最終有節點處理就可以了,到底誰處理是透明的。而且,消息是可以定制的,可以根據情況傳任意數據,而且推拉模式都行。消息節點是消息的發送位置同時也是接收位置,每個消息節點決定自己可以處理那些消息,處理不了的不用管,處理消息也分為向上流動的消息和向下流動的消息。
template<class MessageCodeType>
class CMessage
{
public:
??? CMessage(MessageCodeType code):m_code(code){};
??? virtual ~CMessage(){};
public:
??? MessageCodeType GetCode()
??? {
??????? return m_code;
??? }
private:
??? MessageCodeType m_code;
};
template<class MessageType,class MessageCodeType>
class CMessageNode
{
public:
??? typedef MessageType????????? Message;
??? typedef CMessageNode<Message,MessageCodeType> MessageNode;
??? typedef set<MessageNode* >?? NodeSet;
??? typedef set<MessageCodeType> MessageFilterSet;
??? typedef typename NodeSet::iterator subIterator;
public:
??? CMessageNode():m_pParent(NULL){};
??? virtual ~CMessageNode()
??? {
??????? if(NULL != m_pParent)
??????? {
??? ??? ??? m_pParent->RemoveSubNode(this);
??????? }
??????? for(subIterator it = m_setSubNodes.begin();it!=m_setSubNodes.end();it++)
??????? {
??????????? (*it)->m_pParent = NULL;
??????? }
??? };
public:
??? bool SetParNode(MessageNode* pPar)
??? {
??????? if(NULL != m_pParent)
??????? {
??? ??????? m_pParent->RemoveSubNode(this);
??????? }
??????? if(NULL == pPar)
??????? {
??????????? m_pParent = NULL;
??????????? return true;
??????? }
??????? return pPar->AddSubNode(this);
??? }
??? MessageNode* GetParNode()
??? {
??????? return m_pParent;
??? }
??? bool AddSubNode(MessageNode* pNode)
??? {
??????? if(m_setSubNodes.insert(pNode).second)
??????? {
??????????? pNode->m_pParent = this;
??????????? return true;
??????? }
??????? return false;
??? }
??? bool FindSubNode(MessageNode* pNode)
??? {
??????? return m_setSubNodes.find(pNode)!=m_setSubNodes.end();
??? }
??? bool RemoveSubNode(MessageNode* pNode)
??? {
??????? subIterator it = m_setSubNodes.find(pNode);
??????? if(it == SubEnd())
??????????? return false;
??????? (*it)->m_pParent = NULL;
??????? m_setSubNodes.erase(it);
??????? return true;
??? }
??? int GetSubNodeCount()
??? {
??????? return (int)m_setSubNodes.size();
??? }
??? subIterator SubBegin()
??? {
??????? return m_setSubNodes.begin();
??? }
??? subIterator SubEnd()
??? {
??????? return m_setSubNodes.end();
??? }
??? //添加向上經過此點的消息過濾
??? void AddUpMessageFiltrateItem(MessageCodeType code)
??? {
??????? m_setMessageUpFilter.insert(code);
??? }
??? //添加向下經過此點的消息過濾
??? void AddDownMessageFiltrateItem(MessageCodeType code)
??? {
??????? m_setMessageDownFilter.insert(code);
??? }
??? void ClearUpMessageFilter()
??? {
??????? m_setMessageUpFilter.clear();
??? }
??? void ClearDownMessageFilter()
??? {
??????? m_setMessageDownFilter.clear();
??? }
??? void DeleteUpMessageFiltrateItem(MessageCodeType code)
??? {
??????? m_setMessageUpFilter.erase(code);
??? }
??? void DeleteDownMessageFiltrateItem(MessageCodeType code)
??? {
??????? m_setMessageDownFilter.erase(code);
??? }
protected:
??? //如果處理了返回true,否則返回false
??? void SendUpMessage(Message* pM)
??? {
??????? if(NULL != m_pParent)
??????? ??? SendUpMessage(m_pParent,pM);
??? }
???
??? //如果處理了返回true,否則返回false
??? void SendDownMessage(Message* pM)
??? {
??????? for(subIterator it = SubBegin();it!=SubEnd();it++)
??????? {
??????????? SendDownMessage(*it,pM);
??????? }
??? }
public:
??? static void SendUpMessage(MessageNode* pNode,Message* pM)
??? {
??????? pNode->MessageFromDown(pM);
??? }
??? static void SendDownMessage(MessageNode* pNode,Message* pM)
??? {
??????? pNode->MessageFromUp(pM);
??? }
private:
??? //轉接來自于SubNode的消息
??? //如果處理了則返回true
??? //否則返回false
??? void MessageFromDown(Message* pM)
??? {
??????? if(m_setMessageUpFilter.find(pM->GetCode()) != m_setMessageUpFilter.end())
??????????? return;
??????? //如果本節點沒有處理
??????? if(!OnUpMessage(pM))
?????????? SendUpMessage(pM);
??? }
??? //轉接來自于Par的消息
??? void MessageFromUp(Message* pM)
??? {
??????? if(m_setMessageDownFilter.find(pM->GetCode()) != m_setMessageDownFilter.end())
??????????? return;
???????
??????? //如果本節點沒有處理消息
??????? //則送子節點繼續處理并返回處理結果
??????? if(!OnDownMessage(pM))
??????????? SendDownMessage(pM);
??? }
protected:
??? //經過此節點的上行消息
??? //返回true表示此節點已經處理消息,消息不上傳
??? //返回false消息向上傳
??? virtual bool OnUpMessage(Message* pM)
??? {
??????? return false;
??? }
??? //經過此節點的下行消息
??? //返回true:消息不再向下傳遞
??? //false:消息繼續傳遞
??? virtual bool OnDownMessage(Message* pM)
??? {
??????? return false;
??? }
private:
??? MessageNode* m_pParent;
??? NodeSet m_setSubNodes;
???
??? //過濾向下經過此點的消息
??? MessageFilterSet m_setMessageDownFilter;
???
??? //過濾向上經過此點的消息
??? MessageFilterSet m_setMessageUpFilter;
};
應用實例:
/*定義消息和節點*/
/*定義一種消息,使用正整形作為消息碼,一棵消息樹上消息碼不能重,一個碼代表一個消息*/
class Message : public CMessage<UINT>{
public:
??? Message(UINT key);
??? virtual ~Message();
};
//
/*定義消息節點,定義了處理消息的類型和消息碼類型*/
class MessageNode : public CMessageNode<Message,UINT>
{
public:
??? MessageNode();
??? virtual ~MessageNode();
};
/*建立消息樹和消息*/
#define MSG_SET_PARA??????? 100
#define MSG_UPDATE_NODE_B?? 101
class Message_Set_Para : public Message
{
public:
Message_Set_Para(int _para):Message(MSG_SET_PARA),para(_para){}
public:
int para;
}
class RootNode : public MessageNode
{
protected:
virtual bool OnUpMessage(Message* pM)
??? {
??????? UINT code = pM->GetCode();
??????? if(MSG_SET_PARA == code)
??????? {
??????????? Message_Set_Para* pPara = dynamic_cast< Message_Set_Para*>(pM);
??????????? /*do somthing*/
??????????? return true;/*true:消息不再傳遞,到此為止,false:消息繼續傳遞*/
??????? }
??????? else if(MSG_UPDATE_NODE_B == code)
??????? {//從節點B發出的更新消息
???????????? /*do somthing*/
???????????? return true;
??????? }
??????? __surper::OnUpMessage(pM);
??? }
??? //經過此節點的下行消息
??? //返回true:消息不再向下傳遞
??? //false:消息繼續傳遞
??? virtual bool OnDownMessage(Message* pM)
??? {
??????? return false;
??? }
}
class Node_A : public MessageNode
{
public:
?void set_para1()
{
Message_Set_Para msg(2);
SendUpMessage(&msg);
}
}
class Node_B : public MessageNode
{
public:
???? void update()
{
???? SendUpMessage(&Message(MSG_UPDATE_NODE_B));
}
}
RootNode root;
Node_A a;
Node_B b;
a.SetParNode(&root);
b.SetParNoe(&root);
b.update();
a.set_para1();
MessageNode::SendUpMessage(&b,Message_Set_Para(5));
如例:消息和消息樹有多重定義方法,有多種變化用法,適用場景極多。
在此例中,不免使用了動態類型轉換等不雅行為,后面內容講到訪問者模式的時候就可以一并處理了。
總結
- 上一篇: Lattice FPGA 使用指南4 -
- 下一篇: 2017年腾讯笔试题目