C++ 组合模式(Composite Pattern)

组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示"部分-整体"的层次结构。组合模式使得客户端对单个对象和组合对象的使用具有一致性,也就是说,组合对象和单个对象对客户端来说是透明的,客户端无需关心它们是一个单独的对象还是一个包含子对象的组合对象。

组合模式的主要角色:

  1. 组件(Component):组件是组合模式中所有对象的基类,它为所有派生类提供一个公共接口。通常包含一些操作子节点的方法,比如添加、移除等。
  2. 叶子(Leaf):叶子节点表示树形结构中的叶子对象。叶子没有子节点,它实现了组件接口中的操作,但通常不支持子节点的相关操作。
  3. 组合(Composite):组合节点表示有子节点的复杂对象。它通常存储子节点,并定义了操作子节点的方法。

组合模式的结构:

class Component {
public:
    virtual void Operation() = 0; // 定义接口操作
    virtual void Add(Component* component) {}
    virtual void Remove(Component* component) {}
    virtual Component* GetChild(int index) { return nullptr; }
    virtual ~Component() = default;
};

class Leaf : public Component {
public:
    void Operation() override {
        // 叶子节点的具体操作
        std::cout << "Leaf Operation" << std::endl;
    }
};

class Composite : public Component {
private:
    std::vector<Component*> children;
public:
    void Operation() override {
        // 组合对象的具体操作,通常会递归调用子节点的操作
        for (Component* child : children) {
            child->Operation();
        }
    }

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

    void Remove(Component* component) override {
        children.erase(std::remove(children.begin(), children.end(), component), children.end());
    }

    Component* GetChild(int index) override {
        if (index >= 0 && index < children.size()) {
            return children[index];
        }
        return nullptr;
    }
};

使用组合模式的场景:

  1. 表示对象的部分-整体层次结构:当你想表示一个对象的部分-整体层次结构时,可以使用组合模式。
  2. 希望用户忽略组合对象与单个对象的不同:用户将统一地使用组合结构中的所有对象,而无需关心它们是单个对象还是组合对象。

示例代码

下面是一个使用组合模式的小例子,假设你要表示一个文件系统结构:

#include <iostream>
#include <vector>
#include <algorithm>

// 定义Component基类
class FileSystemComponent {
public:
    virtual void Display() = 0;
    virtual ~FileSystemComponent() = default;
};

// 定义叶子节点
class File : public FileSystemComponent {
private:
    std::string name;
public:
    File(const std::string& name) : name(name) {}
    void Display() override {
        std::cout << "File: " << name << std::endl;
    }
};

// 定义组合节点
class Directory : public FileSystemComponent {
private:
    std::string name;
    std::vector<FileSystemComponent*> children;
public:
    Directory(const std::string& name) : name(name) {}
    
    void Add(FileSystemComponent* component) {
        children.push_back(component);
    }
    
    void Display() override {
        std::cout << "Directory: " << name << std::endl;
        for (auto& child : children) {
            child->Display();
        }
    }
    
    ~Directory() {
        for (auto& child : children) {
            delete child;
        }
    }
};

int main() {
    Directory* root = new Directory("root");
    root->Add(new File("file1.txt"));
    root->Add(new File("file2.txt"));
    
    Directory* subDir = new Directory("subdir");
    subDir->Add(new File("file3.txt"));
    root->Add(subDir);
    
    root->Display();
    
    delete root;
    return 0;
}

在这个示例中,我们定义了一个简单的文件系统,其中包含文件(叶子节点)和目录(组合节点)。Directory对象可以包含多个文件或子目录,通过组合模式,我们可以递归地显示整个文件系统的结构。

这个模式在需要处理树形结构并且希望客户代码能统一处理单个对象和组合对象时非常有用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

先天无极编程圣体

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

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

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

打赏作者

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

抵扣说明:

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

余额充值