zoukankan      html  css  js  c++  java
  • c++ 组合模式(composite)

    原文地址:http://www.cnblogs.com/jiese/p/3168844.html

    当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

    基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。

    用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合二写一些选择判断语句了。

    组合模式让客户可以一致地使用组合结构和单个对象。

    抽象基类:
    1)Component:为组合中的对象声明接口,声明了类共有接口的缺省行为(如这里的Add,Remove,GetChild函数),声明一个接口函数可以访问Component的子组件.

    接口函数:
    1)Component::Operatation:定义了各个组件共有的行为接口,由各个组件的具体实现.
    2)Component::Add添加一个子组件
    3)Component::Remove::删除一个子组件.
    4)Component::GetChild:获得子组件的指针.

    说明:
    Component模式是为解决组件之间的递归组合提供了解决的办法,它主要分为两个派生类:

    1)、Leaf是叶子结点,也就是不含有子组件的结点

    2)、Composite是含有子组件的类.

    举一个例子来说明这个模式,在UI的设计中,最基本的控件是诸如Button、Edit这样的控件,相当于是这里的Leaf组件,而比较复杂的控件 比如Panel则可也看做是由这些基本的组件组合起来的控件,相当于这里的Composite,它们之间有一些行为含义是相同的,比如在控件上作一个点 击,移动操作等等的,这些都可以定义为抽象基类中的接口虚函数,由各个派生类去实现之,这些都会有的行为就是这里的Operation函数,而添加、删除 等进行组件组合的操作只有非叶子结点才可能有,所以虚拟基类中只是提供接口而且默认的实现是什么都不做。

    代码如下:

    composite.h

    #ifndef _COMPOSITE_H_
    #define _COMPOSITE_H_
    
    #include <vector>
    
    using namespace std;
    
    /*
    Component抽象基类,为组合中的对象声明接口,声明了类共有接口的缺省行为(如这里的Add,Remove,GetChild函数),
    声明一个接口函数可以访问Component的子组件.
    */
    class Component
    {
    public:
        //纯虚函数,只提供接口,没有默认的实现
        virtual void Operation()=0;    
    
        // 虚函数,提供接口,有默认的实现就是什么都不做
        virtual void Add(Component*);
        virtual void Remove(Component*);
        virtual Component* GetChild(int index);
        virtual ~Component();
    protected:
        Component();
    };
    
    //Leaf是叶子结点,也就是不含有子组件的结点类,所以不用实现Add、Remove、GetChild等方法
    class Leaf:public Component
    {
    public:
        //只实现Operation接口
        virtual void Operation();            
        Leaf();
        ~Leaf();
    };
    
    //Composite:含有子组件的类
    class Composite:public Component
    {
    public:
        Composite();
        ~Composite();
        //实现所有接口
        void Operation();
        void Add(Component*);
        void Remove(Component*);
        Component* GetChild(int index);
    private:
        //这里采用vector来保存子组件
        vector<Component*> m_ComVec;        
    };
    #endif

    composite.cpp

    #include "Composite.h"
    #include <iostream>
    
    using namespace std;
    
    Component::Component()
    {}
    
    Component::~Component()
    {}
    
    void Component::Add(Component* com)
    {
        cout << "add" << endl;
    }
    
    void Component::Remove(Component* com)
    {
    }
    
    void Component::Operation()
    {
        cout << "Component::Operation" << endl;
    }
    
    Component* Component::GetChild(int index)
    {
        return NULL;
    }
    
    
    Leaf::Leaf()
    {}
    
    Leaf::~Leaf()
    {}
    
    void Leaf::Operation()
    {
        cout<< "Leaf::Operation" <<endl;
    }
    
    Composite::Composite()
    {
    }
    
    Composite::~Composite()
    {}
    
    void Composite::Add(Component* com)
    {
        this->m_ComVec.push_back(com);
    }
    
    void Composite::Remove(Component* com)
    {
        //this->m_ComVec.erase(com);
    }
    
    void Composite::Operation()
    {
        cout << "Composite::Operation" << endl;
        vector<Component*>::iterator iter = this->m_ComVec.begin();
        for(;iter!= this->m_ComVec.end();iter++)
        {
            (*iter)->Operation();
        }
    }
    
    Component* Composite::GetChild(int index)
    {
        if(index < 0 || index > this->m_ComVec.size())
        {
            return NULL;
        }
        return this->m_ComVec[index];
    }

    main.cpp

    #include "composite.h"
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        /*
          不管是叶子Leaf还是Composite对象pRoot、pCom都实现了Operation接口,所以可以一致对待,直接调用Operation()
          体现了“使得用户对单个对象和组合对象的使用具有一致性。”
        */
        Composite* pRoot = new Composite();
    
        //组合对象添加叶子节点
        pRoot->Add(new Leaf());
    
        Leaf* pLeaf1 = new Leaf();
        Leaf* pLeaf2 = new Leaf();
    
        //这里的叶子再添加叶子是没有意义的。
        //由于叶子与组合对象继承了相同的接口,所以语法上是对的,实际上什么也没做(继承自基类Component的Add方法)。
        //叶子节点只实现了Operation方法,其他Add、Remove、GetChild都继承自基类,没有实际意义。
        pLeaf1->Add(pLeaf2);
        pLeaf1->Remove(pLeaf2);
        //执行叶子Operation操作
        pLeaf1->Operation();
    
        //组合对象实现了基类Component的所有接口,所以可以做各种操作(Add、Remove、GetChild、Operation)。
        Composite* pCom = new Composite();
        //组合对象添加叶子节点
        pCom->Add(pLeaf1);
        //组合对象添加叶子节点
        pCom->Add(pLeaf2);
        //执行组合对象Operation操作
        pCom->Operation();
    
        //组合对象添加组合对象
        pRoot->Add(pCom);
    
        //执行组合对象Operation操作
        pRoot->Operation();
    
        //Component* cp = pCom->GetChild(0);
        //cp->Operation();
    
        //pCom->Remove(pLeaf1);
        
        system("pause");
        return 0;
    }
  • 相关阅读:
    通过json动态创建控制器
    记一次bug解决!改变思路解决问题的同时,还需要弄明白是什么原因。
    __proto__,prototype,constructor
    事件:compositionstart & compositionend,解决oninput获取到拼音的问题。
    事件绑定----阻止冒泡失效
    预装的win10系统如何恢复
    rem.js
    vscode 使用 github仓库
    nginx使用
    伸缩盒
  • 原文地址:https://www.cnblogs.com/onlycxue/p/3483234.html
Copyright © 2011-2022 走看看