大家好,欢迎来到IT知识分享网。
消息树,并不是公认的设计模式之一,是本人根据观察者模式发展来的,并于软件实践中得以广泛应用,已经是本人的支柱编码结构。
观察者模式是观察者、被观察者,两者有从属关系,被观察者主动改变,通知观察者。并且在观察者更新的时候也有不方便的地方(见模式之观察者模式)。下面是笔者设计的消息树:
消息树分两部分,消息和消息节点。消息节点可以组成树状结构(消息节点有父子关系:一父多子)。消息就在消息树上跑。由于面向对象编程的编程方式,很自然的会形成很多树状结构的东西,而且,为了方便协调需要通信。消息树建立了一个树状通信通道,任意节点都是消息的发起位置,也是消息的处理位置,消息在树上有两种流动模式,向上即向根节点流动是单条流动路线,向下即向叶子节点流动是广播,广播节点以下都能收到消息。消息发出后沿树流动直到有节点处理后返回,这种发消息,处理消息可以是消息树的若干级之间。对于一个节点,它发消息,不用管谁处理,只要明白向父节点发还是广播给子节点,最终有节点处理就可以了,到底谁处理是透明的。而且,消息是可以定制的,可以根据情况传任意数据,而且推拉模式都行。消息节点是消息的发送位置同时也是接收位置,每个消息节点决定自己可以处理那些消息,处理不了的不用管,处理消息也分为向上流动的消息和向下流动的消息。
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));
如例:消息和消息树有多重定义方法,有多种变化用法,适用场景极多。
在此例中,不免使用了动态类型转换等不雅行为,后面内容讲到访问者模式的时候就可以一并处理了。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/153084.html