QT/C++设计模式_组合模式的理解和举例

[定义]:

        在GOF的《设计模式 : 可复用面向对象软件的基础》一书中对组合模式是这样说的:
将对象组合成树形结构以表示“部分 - 整体”的层次结构。组合(Composite)模式使得用户对单个对象和组合对象的使用具有一致性。

[理解]
        组合模式(Composite)将小对象组合成树形结构,使用户操作组合对象如同操作一个单个对象。组合模式定义了“部分 - 整体”的层次结构,基本对象可以被组合成更大的对象,而且这种操作是可重复的,不断重复下去就可以得到一个非常大的组合对象,但这些组合对象与基本对象拥有相同的接口,因而组合是透明的,用法完全一致。

        我们这样来简单的理解组合模式,组合模式就是把一些现有的对象或者元素,经过组合后组成新的对象,新的对象提供内部方法,可以让我们很方便的完成这些元素或者内部对象的访问和操作。我们也可以把组合对象理解成一个容器,容器提供各种访问其内部对象或者元素的API,我们只需要使用这些方法就可以操作它了。

[使用场景]
        你想表示对象的部分 - 整体层次结构;希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。引用大话设计模式的片段:“当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。”

[总结]
        将对象组合成树形结构以表示“部分 - 整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
        组合模式意图是通过整体与局部之间的关系,通过树形结构的形式进行组织复杂对象,屏蔽对象内部的细节,对外展现统一的方式来操作对象,是我们处理更复杂对象的一个手段和方式。

[举例说明]

1. 上面公司的结构图其实就是整体与部分的关系,而且的话整体与部分可以一致对待,因为有很多相似之处嘛。

2. 这棵树有两种几能,要么是棵叶,要么是子棵。
其实这种模式就是组合模式

要注意两点:

1. “树形”,必须是一种层次结构,有可以向下延伸的分枝,也有不变的树叶。

2. "一致性",也就是要具有很多相似性。

#include <iostream>
#include <list>
#include <memory>
#include <utility>
#include <cstddef>
#include<string>
using namespace std;

class Company
{
public:
    Company(string name) { m_name = name; }
    virtual ~Company() {}
    virtual void Add(std::unique_ptr<Company>) {}//这里默认实现为空函数,leaf节点中不用实现为空了
    virtual void Show(int depth) {} // 这里默认实现为空函数,leaf节点中不用实现为空了
protected:
    string m_name;
};

//具体公司
class ConcreteCompany : public Company
{
public:
    ConcreteCompany(string name) : Company(name) {}
    virtual ~ConcreteCompany()
    {
        for (auto& company : m_listCompany)
        {
            company.reset(nullptr);
        }
    }
    void Add(std::unique_ptr<Company> pCom) { m_listCompany.push_back(std::move(pCom)); } //位于树的中间,可以增加子树
    void Show(int depth)
    {
        for (int i = 0; i < depth; i++)
            cout << "-";
        cout << m_name << endl;
        auto iter = m_listCompany.begin();
        for (; iter != m_listCompany.end(); iter++) //显示下层结点
            (*iter)->Show(depth + 2);
    }
private:
    list<std::unique_ptr<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()
{
    auto root = std::make_unique<ConcreteCompany>("总公司");
    auto leaf1 = std::make_unique < FinanceDepartment>("总公司财务部");
    auto leaf2 = std::make_unique < HRDepartment>("总公司人力资源部");
    root->Add(std::move(leaf1));
    root->Add(std::move(leaf2));

    //分公司
    auto mid1 = std::make_unique < ConcreteCompany>("杭州分公司");
    auto leaf3 = std::make_unique < FinanceDepartment>("杭州分公司财务部");
    auto leaf4 = std::make_unique < HRDepartment>("杭州分公司人力资源部");
    mid1->Add(std::move(leaf3));
    mid1->Add(std::move(leaf4));
    root->Add(std::move(mid1));
    //分公司
    auto mid2 = std::make_unique < ConcreteCompany>("上海分公司");
    auto leaf5 = std::make_unique < FinanceDepartment>("上海分公司财务部");
    auto leaf6 = std::make_unique < HRDepartment>("上海分公司人力资源部");
    mid2->Add(std::move(leaf5));
    mid2->Add(std::move(leaf6));
    root->Add(std::move(mid2));
    root->Show(0);


    return 0;
}
//输出
//总公司
//--总公司财务部
//--总公司人力资源部
//--杭州分公司
//----杭州分公司财务部
//----杭州分公司人力资源部
//--上海分公司
//----上海分公司财务部
//----上海分公司人力资源部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值