模式之消息树

消息树,并不是公认的设计模式之一,是本人根据观察者模式发展来的,并于软件实践中得以广泛应用,已经是本人的支柱编码结构。

观察者模式是观察者、被观察者,两者有从属关系,被观察者主动改变,通知观察者。并且在观察者更新的时候也有不方便的地方(见模式之观察者模式)。下面是笔者设计的消息树:

消息树分两部分,消息和消息节点。消息节点可以组成树状结构(消息节点有父子关系:一父多子)。消息就在消息树上跑。由于面向对象编程的编程方式,很自然的会形成很多树状结构的东西,而且,为了方便协调需要通信。消息树建立了一个树状通信通道,任意节点都是消息的发起位置,也是消息的处理位置,消息在树上有两种流动模式,向上即向根节点流动是单条流动路线,向下即向叶子节点流动是广播,广播节点以下都能收到消息。消息发出后沿树流动直到有节点处理后返回,这种发消息,处理消息可以是消息树的若干级之间。对于一个节点,它发消息,不用管谁处理,只要明白向父节点发还是广播给子节点,最终有节点处理就可以了,到底谁处理是透明的。而且,消息是可以定制的,可以根据情况传任意数据,而且推拉模式都行。消息节点是消息的发送位置同时也是接收位置,每个消息节点决定自己可以处理那些消息,处理不了的不用管,处理消息也分为向上流动的消息和向下流动的消息。

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));

如例:消息和消息树有多重定义方法,有多种变化用法,适用场景极多。

在此例中,不免使用了动态类型转换等不雅行为,后面内容讲到访问者模式的时候就可以一并处理了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值