设计模式之《组合模式》

介绍

组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。[DP]属于结构型模式之一。

  • Component抽象构件角色
    定义参加组合对象的共有方法和属性, 可以定义一些默认的行为或属性。
  • Leaf叶子构件
    叶子对象, 其下再也没有其他的分支, 也就是遍历的最小单位。
  • Composite树枝构件
    树枝对象, 它的作用是组合树枝节点和叶子节点形成一个树形结构

透明组合模式中,抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法,这样做的好处是确保所有的构件类都有相同的接口。此模式中Component、Leaf、Composite均需要实现所有方法,对于leaf实际上add等方法是无意义的,但对于client来说不需要区分Leaf和Composite。

安全组合模式中,在抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。

优点: 高层模块调用简单;节点自由增加

缺点: 树叶和树枝使用实现类,不符合依赖倒置 

应用:维护和展示部分–整体关系的场景,如树形菜单、文件和文件夹管理;从一个整体中能够独立出部分模块或功能的场景。

 UML图:

#ifndef SIMPLE_COMPOSITE_H
#define SIMPLE_COMPOSITE_H

#include <iostream>
#include <list>

using namespace std;

/**
 * @brief The Component class
 * Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个
 * 接口用于访问和管理Component的子部件。
 */
class Component
{
public:
    Component(string name)
    {
        m_name = name;
    }

    virtual int add(Component *c) = 0;
    virtual int remove(Component *c) = 0;
    virtual void display(int depth) = 0;
protected:
    string m_name;
};

/**
 * @brief The Leaf class
 * Leaf在组合中表示叶节点对象,叶节点没有子节点。
 */
class Leaf : public Component
{
public:
    Leaf(string name)
        :Component(name)
    {

    }

    int add(Component *c) override
    {
        cout<<" Cannot add to a leaf\n";
        return -1;
    }

    int remove(Component *c) override
    {
        cout<< " Cannot remove from a leaf\n";
        return -1;
    }

    void display(int depth) override
    {
        for (int i=0 ;i<depth ;i++) {
            cout<<"-";
        }
        cout<<m_name<<endl;
    }
};

/**
 * @brief The Composite class
 * Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,
 * 比如增加Add和删除Remove。
 */
class Composite : public Component
{
public:
    Composite(string name)
        :Component(name)
    {
        m_list = new list<Component*>;
        m_list->clear();
    }

    int add(Component *c) override
    {
        m_list->push_back(c);
        return m_list->size();
    }

    int remove(Component *c) override
    {
        m_list->remove(c);
        return m_list->size();
    }

    void display(int depth) override
    {
        for (int i=0 ;i<depth ;i++) {
            cout<<"-";
        }
        cout<<m_name<<endl;
        for (list <Component *>::iterator it = m_list->begin(); it!= m_list->end(); it++) {
           (*it)->display(2+depth);
        }
    }
private:
    list <Component *> *m_list;
};



#endif // SIMPLE_COMPOSITE_H

调用:

    //生成树根root,根上长出两叶LeafA和LeafB
    Composite *root = new Composite("root");
    root->add(new Leaf("Leaf A"));
    root->add(new Leaf("Leaf B"));

    //根上长出分枝Composite X,分枝上也有两叶LeafXA和LeafXB
    Composite *comp = new Composite("Composite X");
    comp->add(new Leaf("Leaf XA"));
    comp->add(new Leaf("Leaf XB"));

    root->add(comp);

    //在Composite X.上再长 出分枝CompositeXY,分枝上也有两叶LeafXYA和LeafXYB
    Composite *comp2 = new Composite("Composite XY");
    comp2->add(new Leaf("Leaf XYA"));
    comp2->add(new Leaf("Leaf XYB"));

    comp->add(comp2);

    //根部又长出两叶LeafC和LeafD
    root->add(new Leaf("Leaf C"));

    Leaf *le = new Leaf( "Leaf D");
    root->add(le);
    //可惜LeafD没长牢,被风吹走了
    root->remove(le);
    root->display(1);

 

公司管理系统:

UML类图:

代码:

#ifndef COMPANY_MANAGER_H
#define COMPANY_MANAGER_H

#include <iostream>
#include <string>
#include <list>
using namespace std;

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

    virtual int add(Company *) = 0;
    virtual int remove(Company *) = 0;
    virtual void display(int depth) = 0;
    virtual void lineOfDuty() = 0;//旅行职责
protected:
    string m_name;
};

/**
 * @brief The ConcreteCompany class
 * 具体公司类,实现接口,树枝节点
 */
class ConcreteCompany : public Company
{
public:
    ConcreteCompany(string name)
        :Company(name)
    {
        m_list = new list <Company *>;
        m_list->clear();
    }

    int add(Company *c) override
    {
        m_list->push_back(c);
        return m_list->size();
    }
    int remove(Company *c) override
    {
        m_list->remove(c);
        return m_list->size();
    }
    void display(int depth) override
    {
        for (int i=0 ;i<depth ;i++) {
            cout<<"-";
        }
        cout<<m_name<<endl;
        for (list <Company *>::iterator it = m_list->begin(); it!= m_list->end(); it++) {
           (*it)->display(2+depth);
        }

    }
    void lineOfDuty() override
    {
        for (list <Company *>::iterator it = m_list->begin(); it!= m_list->end(); it++) {
           (*it)->lineOfDuty();
        }
    }

private:
    list <Company *> *m_list;
};

/**
 * @brief The HRDepartment class
 * 人力资源部门,叶子节点
 */
class HRDepartment : public Company
{
public:
    HRDepartment(string name)
        :Company(name)
    {
    }

    int add(Company *) override
    {
        return -1;
    }
    int remove(Company *) override
    {
        return -1;
    }
    void display(int depth) override
    {
        for (int i=0 ;i<depth ;i++) {
            cout<<"-";
        }
        cout<<m_name<<endl;
    }
    void lineOfDuty() override
    {
        cout<<m_name <<"  员工招聘培训管理\n";
    }

};


class FinaceDepartment : public Company
{
public:
    FinaceDepartment(string name)
        :Company(name)
    {
    }

    int add(Company *) override
    {
        return -1;
    }
    int remove(Company *) override
    {
        return -1;
    }
    void display(int depth) override
    {
        for (int i=0 ;i<depth ;i++) {
            cout<<"-";
        }
        cout<<m_name<<endl;
    }
    void lineOfDuty() override
    {
        cout<<m_name <<"  公司财务收支管理\n";
    }

};

#endif // COMPANY_MANAGER_H

调用:

 ConcreteCompany *root = new  ConcreteCompany("北京分公司");
    root->add(new HRDepartment("总公司人力资源部"));
    root->add(new FinaceDepartment("总公司财务部"));

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

    ConcreteCompany *comp1 = new ConcreteCompany("南京华东分公司");
    comp1->add(new HRDepartment("南京分公司人力资源部"));
    comp1->add(new FinaceDepartment("南京分公司财务部"));
    root->add(comp1);


    ConcreteCompany *comp2 = new ConcreteCompany("杭州华东分公司");
    comp2->add(new HRDepartment("杭州分公司人力资源部"));
    comp2->add(new FinaceDepartment("杭州分公司财务部"));
    root->add(comp2);

    cout<<"\n结构图:\n";
    root->display(1);

    cout<<"\n职责\n";
    root->lineOfDuty();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liu-Eleven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值