第十九章-组合模式

Posted wfcg165

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十九章-组合模式相关的知识,希望对你有一定的参考价值。

组合模式(Composite): 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

技术图片

基本代码

#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Component
{
protected:
    string name;
public:
    Component(string name_t)
    {
        name = name_t;
    }

    virtual void Add(Component* c) = 0;
    virtual void Remove(Component* c) = 0;
    virtual void Display(int depth) = 0;
};

class Leaf :public Component
{
public:
    Leaf(string name_t)
        :Component(name_t)
    { }

    void Add(Component* c)
    {
        cout << "Cannot add to a lead" << endl;
    }

    void Remove(Component* c)
    {
        cout << "Cannot remove from a lead" << endl;
    }

    void Display(int depth)
    {
        cout << string(depth, '-') << " " << name << endl;
    }
};

class Composite :public Component
{
private:
    vector<Component*> children;
public:
    Composite(string name_t)
        :Component(name_t)
    { }

    void Add(Component* c)
    {
        children.push_back(c);
    }

    void Remove(Component* c)
    {
        for (auto _i = children.begin(); _i != children.end(); _i++)
        {
            if (*_i == c)
            {
                children.erase(_i);
                break;
            }
        }
    }

    void Display(int depth)
    {
        cout << string(depth, '-') << " " << name << endl;
        for (auto _i : children)
        {
            _i->Display(depth + 2);
        }
    }
};



int main()
{
    Composite* root = new Composite("root");
    root->Add(new Leaf("Leaf A"));
    root->Add(new Leaf("Leaf B"));

    Composite* comp = new Composite("Composite X");
    comp->Add(new Leaf("Leaf XA"));
    comp->Add(new Leaf("Leaf XB"));

    root->Add(comp);

    Composite* comp2 = new Composite("Composite XY");
    comp2->Add(new Leaf("Leaf XYA"));
    comp2->Add(new Leaf("Leaf XYB"));

    comp->Add(comp2);

    root->Add(new Leaf("Leaf C"));

    Leaf* leaf = new Leaf("Leaf D");
    root->Add(leaf);
    root->Remove(leaf);

    root->Display(1);



    system("pause");
    return 0;
}

透明方式与安全方式

  • 透明方式,也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等,这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它们是没有意义的。
  • 安全方式,也就是在Component接口中不去声明Add和Remove方法,那么子类的Lead也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样就不会出现上面的问题,不过由于不够透明,所以树叶和树枝类将不具备相同的接口,客户端的调用需要做相应的判断,带来了不便。

公司管理系统

技术图片

#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Company
{
protected:
    string name;
public:
    Company(string name_t)
    {
        name = name_t;
    }

    virtual void Add(Company* c) = 0;
    virtual void Remove(Company* c) = 0;
    virtual void Display(int depth) = 0;
    virtual void LineOfDuty() = 0;
};

class ConcreteCompany :public Company
{
private:
    vector<Company*> children;
public:
    ConcreteCompany(string name_t)
        :Company(name_t)
    { }

    void Add(Company* c)
    {
        children.push_back(c);
    }

    void Remove(Company* c)
    {
        for (auto _i = children.begin(); _i != children.end(); _i++)
        {
            if (*_i == c)
            {
                children.erase(_i);
                break;
            }
        }
    }

    void Display(int depth)
    {
        cout << string(depth, '-') << " " << name << endl;
        for (auto _i : children)
        {
            _i->Display(depth + 2);
        }
    }

    void LineOfDuty()
    {
        for (auto _i : children)
        {
            _i->LineOfDuty();
        }
    }
};

class HRDepartment : public Company
{
public:
    HRDepartment(string name_t): Company(name_t)
    { }

    void Add(Company* c)
    { }

    void Remove(Company* c)
    { }

    void Display(int depth)
    {
        cout << string(depth, '-') << " " << name << endl;
    }

    void LineOfDuty()
    {
        cout << name << " 员工招聘培训管理" << endl;
    }
};

class FinanceDepartment : public Company
{
public:
    FinanceDepartment(string name_t) : Company(name_t)
    { }

    void Add(Company* c)
    { }

    void Remove(Company* c)
    { }

    void Display(int depth)
    {
        cout << string(depth, '-') << " " << name << endl;
    }

    void LineOfDuty()
    {
        cout << name << " 公司财务收支管理" << endl;
    }
};

int main()
{
    ConcreteCompany* root = new ConcreteCompany("北京总公司");
    root->Add(new HRDepartment("总公司人力资源部"));
    root->Add(new HRDepartment("总公司财务部"));

    ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
    comp->Add(new HRDepartment("华东分公司人力资源部"));
    comp->Add(new HRDepartment("华东分公司财务部"));
    root->Add(comp);

    ConcreteCompany* comp1 = new ConcreteCompany("南京办事处");
    comp1->Add(new HRDepartment("南京办事处人力资源部"));
    comp1->Add(new HRDepartment("南京办事处财务部"));
    comp->Add(comp1);

    ConcreteCompany* comp2 = new ConcreteCompany("杭州办事处");
    comp2->Add(new HRDepartment("杭州办事处人力资源部"));
    comp2->Add(new HRDepartment("杭州办事处财务部"));
    comp->Add(comp2);

    cout << "
结构图:" << endl;
    root->Display(1);

    cout << "
职责:" << endl;
    root->LineOfDuty();

    system("pause");
    return 0;
}

组合模式可以使基本对象可以被组合成更复杂的组合对象,而这个对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
并且用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。
简单点说,就是组合模式让客户可以一致的使用组合结构和的单个对象。

以上是关于第十九章-组合模式的主要内容,如果未能解决你的问题,请参考以下文章

第十九章枚举集合

第十九章 Django框架——Admin组件

实战:第十九章:存入Long类型对象,在代码中使用Long类型接收,结果报类型转换错误

实战:第十九章:存入Long类型对象,在代码中使用Long类型接收,结果报类型转换错误

WPF学习第十九章 控件类

第十九章 函数的高级话题