• 设计模式 --> (8)组合模式


    组合模式

      组合模式,是为了解决整体和部分的一致对待的问题而产生的,要求这个整体与部分有一致的操作或行为。部分和整体都继承与一个公共的抽象类,这样,外部使用它们时是一致的,不用管是整体还是部分,使用一个方法即可遍历整体中的所有的部分。就像一个树形结构一样。

    适用性:

      常用于组织结构,产品结构之类的整体和部分的结构。例如图形由很多直线构成,直线由点构成,这就是整体和部分的关系。如果采用组合模式,只需要使用一个draw方法即可按遍历的方式画出所有的点,最终呈现出来的就是图形。

    优点:

      隐藏了整体和部分,让外部依赖于抽象,简化了代码。

    缺点:

      1.要求必须有一致的行为。

      2.处于同一个Composite的Leaf与Leaf之间难以传递数据。

    代码实现1

      比如一个集团公司,它有一个母公司,下设很多家子公司。不管是母公司还是子公司,都有各自直属的财务部、人力资源部、销售部等。对于母公司来说,不论是子公司,还是直属的财务部、人力资源部,都是它的部门。整个公司的部门拓扑图就是一个树形结构。

    #include <iostream>
    #include <list>
    #include <string>
    
    using namespace std;
    
    class Company    
    {  
    public:  
        Company(string name) { m_name = name; }  
        virtual ~Company(){}  
        virtual void Add(Company *pCom){}  
        virtual void Show(int depth) {}  
    protected:  
        string m_name;  
    };  
    //具体公司  
    class ConcreteCompany : public Company    
    {  
    public:  
        ConcreteCompany(string name): Company(name) {}  
        virtual ~ConcreteCompany() {}  
        void Add(Company *pCom) { m_listCompany.push_back(pCom); } //位于树的中间,可以增加子树  
        void Show(int depth)  
        {  
            for(int i = 0;i < depth; i++)  
                cout<<"-";  
            cout<<m_name<<endl;  
            list<Company *>::iterator iter=m_listCompany.begin();  
            for(; iter != m_listCompany.end(); iter++) //显示下层结点  
                (*iter)->Show(depth + 2);  
        }  
    private:  
        list<Company *> m_listCompany;  
    };  
    //具体的部门,财务部  
    class FinanceDepartment : public Company   
    {  
    public:  
        FinanceDepartment(string name):Company(name){}  
        virtual ~FinanceDepartment() {}  
        virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点  
        {  
            for(int i = 0; i < depth; i++)  
                cout<<"-";  
            cout<<m_name<<endl;  
        }  
    };  
    //具体的部门,人力资源部  
    class HRDepartment :public Company    
    {  
    public:  
        HRDepartment(string name):Company(name){}  
        virtual ~HRDepartment() {}  
        virtual void Show(int depth) //只需显示,无限添加函数,因为已是叶结点  
        {  
            for(int i = 0; i < depth; i++)  
                cout<<"-";  
            cout<<m_name<<endl;  
        }  
    }; 
    
    int main()  
    {  
        Company *root = new ConcreteCompany("总公司");  
        Company *leaf1=new FinanceDepartment("财务部");  
        Company *leaf2=new HRDepartment("人力资源部");  
        root->Add(leaf1);  
        root->Add(leaf2);  
      
        //分公司A  
        Company *mid1 = new ConcreteCompany("分公司A");  
        Company *leaf3=new FinanceDepartment("财务部");  
        Company *leaf4=new HRDepartment("人力资源部");  
        mid1->Add(leaf3);  
        mid1->Add(leaf4);  
        root->Add(mid1);  
        //分公司B  
        Company *mid2=new ConcreteCompany("分公司B");  
        FinanceDepartment *leaf5=new FinanceDepartment("财务部");  
        HRDepartment *leaf6=new HRDepartment("人力资源部");  
        mid2->Add(leaf5);  
        mid2->Add(leaf6);  
        root->Add(mid2);  
        root->Show(0);  
      
        delete leaf1; delete leaf2;  
        delete leaf3; delete leaf4;  
        delete leaf5; delete leaf6;   
        delete mid1; delete mid2;  
        delete root;  
        return 0;  
    } 

    结果:

    总公司
    --财务部
    --人力资源部
    --分公司A
    ----财务部
    ----人力资源部
    --分公司B
    ----财务部
    ----人力资源部
    请按任意键继续. . .

    上面的实现方式有缺点,就是内存的释放不好,需要客户自己动手,非常不方便。有待改进,比较好的做法是让ConcreteCompany类来释放。因为所有的指针都是存在ConcreteCompany类的链表中。C++的麻烦,没有垃圾回收机制。

    代码实现2

      下面示例有两种情况,add函数对于Leaf来说是没有必要的,所以可以在Leaf的add实现中什么都不写。还一种办法就是将add方法挪到Composite中,让外部使用Composite和Component。但这样的缺点就是暴露了Composite,客户端必须知道Composite才能完成操作,好处Leaf不用产生多余的方法了。

    #include <iostream>
    #include <vector>
    using namespace std;
    
    class Component
    {
      public:
        Component(){};
        virtual ~Component(){};
    
        virtual void operation() = 0;
    };
    
    class Leaf: public Component
    {
      public:
        Leaf(){};
        ~Leaf(){};
    
        void operation() { cout << "Operation leaf" << endl; }
    };
    
    
    class Composite: public Component
    {
      public:
        Composite(){};
        ~Composite(){};
    
        void add(Component* c) { m_leafs.push_back(c); }
        void operation()
        {
            cout << "Operation Composite" << endl;
            vector<Component*>::iterator comIter = m_leafs.begin();    
            for (; comIter != m_leafs.end(); comIter++)
            {
                (*comIter)->operation();
            }
        }
    
      private:
        vector<Component*> m_leafs;
    };
    
    int main()
    {
        Component* leaf1 = new Leaf();
        Component* leaf2 = new Leaf();
    
        Composite* composite1 = new Composite();
        composite1->add(leaf1);
        composite1->add(leaf2);
    
        Composite* composite2 = new Composite();
        composite2->add(composite1);
    
        composite2->operation();
        return 0;
    }

    结果:

    Operation Composite
    Operation Composite
    Operation leaf
    Operation leaf
    请按任意键继续. . .

    参考 : http://blog.csdn.net/wuzhekai1985/article/details/6667564

  • 相关阅读:
    json取值(key是中文或者数字)方式详解
    快速排序
    百度地图 获取矩形point
    ArcGIS
    天眼
    shapefile文件
    SQL Server 2008 的gis函数
    查看某一个点是否在某个多边形内 使用ST_Contains函数
    PostgreSQL+PostGIS的使用 函数清单
    地理坐标计算
  • 原文地址:https://www.cnblogs.com/jeakeven/p/4948427.html
Copyright © 2020-2023  润新知