C++设计模式之组合模式

参考《大话设计模式》的代理模式,把C#改写成c++的实现 。
参考 设计模式C++实现(7)——外观模式、组合模式这篇博客
DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构。组合使得用户对单个对象和组合对象的使用具有一致性。

例如:一个公司有下面有各个部门,还有分公司。分公司和总公司一样,也有不同的部门,下面可以还有分公司。
这里写图片描述

这里使用了智能指针来实现多态可以参考这里

1.公司类(基类)

因为C++里面,抽象类不能实例化,所以这里公司类就没有定义成抽象类了

class Company
{
public:
    Company(string name) { m_name = name; }
    virtual ~Company(){cout<<"删除 "<<m_name<<endl;}
    virtual void Add(shared_ptr<Company> pCom){}
    virtual void remove(shared_ptr<Company> pCom){}

    virtual void Show(int depth)
    {
        for(int i = 0; i < depth; i++)
            cout<<"-";
        cout<<m_name<<endl;
    }
protected:
    string m_name;
};

2.具体公司类(实现接口或者方法)

//具体公司
class ConcreteCompany : public Company
{
public:
    ConcreteCompany(string name): Company(name) {}
    virtual ~ConcreteCompany() {}
    void Add(shared_ptr<Company> pCom) { m_listCompany.push_back(pCom); } //位于树的中间,可以增加子树
    void remove(shared_ptr<Company> pCom){m_listCompany.remove(pCom);}
    void Show(int depth)
    {
        for(int i = 0;i < depth; i++)
            cout<<"-";
        cout<<m_name<<endl;
//        list<shared_ptr<Company>>::iterator iter=m_listCompany.begin();
//        for(; iter != m_listCompany.end(); iter++) //显示下层结点
//            (*iter)->Show(depth + 2);
        for(const auto& company:m_listCompany)
            company->Show(depth+2);
    }
private:
    list<shared_ptr<Company>> m_listCompany;
};

3.两个具体部门

//具体的部门,财务部
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;
    }
};

这两个类其实可以添加Add和remove两个函数,与基类保存一直。但是我觉得这两个部门没有这两个功能,可以不写上。

4.客服端

int main()
{
    shared_ptr<Company> root = make_shared<ConcreteCompany>("总公司");
    shared_ptr<Company> leaf1=make_shared<FinanceDepartment>("总公司人力资源部");
    shared_ptr<Company> leaf2=make_shared<HRDepartment>("总公司财务部");
    root->Add(leaf1);
    root->Add(leaf2);

    //分公司A
    shared_ptr<Company> midA = make_shared<ConcreteCompany>("分公司A");
    shared_ptr<Company> leaf3=make_shared< FinanceDepartment>("分公司A人力资源部");
    shared_ptr<Company> leaf4=make_shared< HRDepartment>("分公司A财务部");
    midA->Add(leaf3);
    midA->Add(leaf4);
    root->Add(midA);
    //分公司B
    shared_ptr<Company> midB=make_shared< ConcreteCompany>("分公司B");
    shared_ptr<Company> leaf5=make_shared< FinanceDepartment>("分公司B人力资源部");
    shared_ptr<Company> leaf6=make_shared< HRDepartment>("分公司B财务部");
    midB->Add(leaf5);
    midB->Add(leaf6);
    root->Add(midB);

    //分公司B_1
    shared_ptr<Company> midB_1=make_shared< ConcreteCompany>("分公司B_1");
    shared_ptr<Company> leaf7=make_shared< FinanceDepartment>("分公司B_1人力资源部");
    shared_ptr<Company> leaf8=make_shared< HRDepartment>("分公司B_1财务部");
    midB_1->Add(leaf7);
    midB_1->Add(leaf8);
    midB->Add(midB_1);

    //分公司A_1
    shared_ptr<Company> midA_1=make_shared< ConcreteCompany>("分公司A_1");
    shared_ptr<Company> leaf9=make_shared< FinanceDepartment>("分公司A_1人力资源部");
    shared_ptr<Company> leaf10=make_shared< HRDepartment>("分公司A_1财务部");
    midA_1->Add(leaf9);
    midA_1->Add(leaf10);
    midA->Add(midA_1);

    shared_ptr<Company> leaf11=make_shared< HRDepartment>("分公司A_2财务部");
    midA->Add(leaf11);
    midA->remove(leaf11);


    root->Show(0);
    return 0;
}

需要添加三个头文件

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

运行结果图:
这里写图片描述

5.总结

这里使用了智能指针来代替内置指针,可以避免手动删除指针。程序结束之后,调用析构函数,自动释放内存。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值