<aside> 💡

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

</aside>

结构图

image.png

透明方式与安全方式

透明方式

安全方式

应用场景

题目

https://kamacoder.com/problempage.php?pid=1090

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

// Component类
class Company{
protected:
    std::string name;

public:
    Company(std::string name): name(name){}
    virtual ~Company(){}

    // 透明模式,定义了管理子类的接口(add)
    virtual void add(Company*) = 0;
    virtual void display(int depth) = 0;
};

// Composite类
class Department: public Company{
private:
    // 管理子类的容器
    std::vector<Company*> employees;

public:
    Department(std::string name): Company(name){}
    // 析构函数中对所有子类进行销毁
    ~Department(){
        for(Company* employee : employees){
            delete employee;
        }
    }

    // 实现了管理子类的方法
    void add(Company* employee) override {
        employees.push_back(employee);
    }

    void display(int depth) override {
        std::string space(depth * 2, ' ');
        std::cout << space << name << std::endl;
        for(Company* employee : employees){
            employee->display(depth + 1);
        }
    }
};

// Left类
class Employee: public Company{
public:
    Employee(std::string name): Company(name){}

    // 叶节点没有子类,也不需要对其进行管理,实现该接口是没有意义的
    void add(Company*) override {
        std::cout << "Cannot add!" << std::endl;
    }

    void display(int depth){
        std::string space(depth * 2, ' ');
        std::cout << space << name << std::endl;
    }
};

int main(){
    std::string companyName;
    std::cin >> companyName;
    Department* myCompany = new Department(companyName);
    Department* department = nullptr;

    int n;
    std::cin >> n;
    for(int i = 0; i < n; ++i){
        std::string type;
        std::string name;
        std::cin >> type >>name;

        if(type == "D"){
            department = new Department(name);
            myCompany->add(department);
        }else if(type == "E"){
            department->add(new Employee(name));
        }
    }

    std::cout << "Company Structure:" << std::endl;
    myCompany->display(0);

    // 只需要销毁根节点,子类由其析构函数负责销毁
    delete myCompany;

    return 0;
}