C++ 组合模式详解

组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构 来表示"部分-整体"的层次结构,使得客户端可以统一处理单个对象和组合对象。

核心概念

设计原则

组合模式遵循以下设计原则:

  1. 单一职责原则:将对象的结构和使用分离

  2. 开闭原则:可以添加新类型的组件而不修改现有代码

  3. 透明性:对单个对象和组合对象提供一致的操作接口

主要优点

  1. 统一处理:客户端可以一致地处理单个对象和组合对象

  2. 简化客户端代码:客户端不需要知道处理的是单个对象还是组合

  3. 灵活的结构:可以轻松添加新的组件类型

  4. 递归组合:支持递归结构,便于表示复杂的层次关系

模式结构

主要组件

  1. Component(抽象组件)

    • 定义所有组件的通用接口

    • 声明访问和管理子组件的方法(可选)

  2. Leaf(叶子组件)

    • 表示组合中的叶子节点(没有子元素)

    • 实现组件接口的基本行为

  3. Composite(复合组件)

    • 存储子组件(可以是Leaf或其他Composite)

    • 实现与子组件相关的操作

完整代码示例

复制代码
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <algorithm>

// ==================== 抽象组件 ====================
class FileSystemComponent {
public:
    virtual void display(int depth = 0) const = 0;
    virtual void add(std::unique_ptr<FileSystemComponent> component) {
        throw std::runtime_error("不支持添加操作");
    }
    virtual void remove(FileSystemComponent* component) {
        throw std::runtime_error("不支持删除操作");
    }
    virtual ~FileSystemComponent() = default;
};

// ==================== 叶子组件 ====================
class File : public FileSystemComponent {
    std::string name_;
    int size_;
    
public:
    File(const std::string& name, int size) : name_(name), size_(size) {}
    
    void display(int depth = 0) const override {
        std::cout << std::string(depth * 2, ' ') 
                  << "- " << name_ << " (" << size_ << " KB)" << std::endl;
    }
};

// ==================== 复合组件 ====================
class Directory : public FileSystemComponent {
    std::string name_;
    std::vector<std::unique_ptr<FileSystemComponent>> children_;
    
public:
    explicit Directory(const std::string& name) : name_(name) {}
    
    void display(int depth = 0) const override {
        std::cout << std::string(depth * 2, ' ') 
                  << "+ " << name_ << " (目录)" << std::endl;
        
        for (const auto& child : children_) {
            child->display(depth + 1);
        }
    }
    
    void add(std::unique_ptr<FileSystemComponent> component) override {
        children_.push_back(std::move(component));
    }
    
    void remove(FileSystemComponent* component) override {
        auto it = std::remove_if(children_.begin(), children_.end(),
            [component](const std::unique_ptr<FileSystemComponent>& ptr) {
                return ptr.get() == component;
            });
        children_.erase(it, children_.end());
    }
};

// ==================== 客户端代码 ====================
int main() {
    std::cout << "=== 文件系统结构 ===" << std::endl;
    
    // 创建根目录
    auto root = std::make_unique<Directory>("根目录");
    
    // 添加文件到根目录
    root->add(std::make_unique<File>("readme.txt", 100));
    root->add(std::make_unique<File>("program.exe", 1024));
    
    // 创建子目录
    auto documents = std::make_unique<Directory>("文档");
    documents->add(std::make_unique<File>("report.doc", 250));
    documents->add(std::make_unique<File>("presentation.ppt", 500));
    
    // 在子目录中再创建子目录
    auto images = std::make_unique<Directory>("图片");
    images->add(std::make_unique<File>("photo1.jpg", 800));
    images->add(std::make_unique<File>("photo2.jpg", 900));
    
    documents->add(std::move(images));
    
    // 将子目录添加到根目录
    root->add(std::move(documents));
    
    // 显示完整的文件系统结构
    root->display();
    
    return 0;
}
复制代码
}

模式变体

1. 透明式组合模式

复制代码
// 在抽象组件中声明所有方法(包括管理子组件的方法)
class Graphic {
public:
    virtual void draw() const = 0;
    virtual void add(std::unique_ptr<Graphic> graphic) {
        throw std::runtime_error("不支持添加操作");
    }
    virtual void remove(Graphic* graphic) {
        throw std::runtime_error("不支持删除操作");
    }
    virtual ~Graphic() = default;
};

2. 安全式组合模式

复制代码
// 只在复合组件中声明管理子组件的方法
class Graphic {
public:
    virtual void draw() const = 0;
    virtual ~Graphic() = default;
};

class CompositeGraphic : public Graphic {
    std::vector<std::unique_ptr<Graphic>> children_;
public:
    void add(std::unique_ptr<Graphic> graphic) {
        children_.push_back(std::move(graphic));
    }
    // ... 其他方法 ...
};

实际应用场景

  1. 文件系统:文件和目录的层次结构

  2. GUI组件:窗口包含面板,面板包含按钮等

  3. 组织结构:公司部门与员工的层次关系

  4. 图形编辑:图形组合与简单图形的统一处理

  5. 菜单系统:菜单项和子菜单的统一处理

相关推荐
_extraordinary_10 分钟前
Java Map和Set
java·开发语言
jingjing~17 分钟前
【Qt】QTime::toString(“hh:mm:ss.zzz“) 显示乱码的原因与解决方案
java·开发语言·qt
励志成为糕手27 分钟前
深入剖析Spring IOC容器——原理、源码与实践全解析
java·开发语言·spring
杨DaB3 小时前
【SpringMVC】拦截器,实现小型登录验证
java·开发语言·后端·servlet·mvc
近津薪荼3 小时前
c++详解(宏与内联函数,nullptr)
开发语言·c++
淮北4944 小时前
STL学习(十一、常用的算数算法和集合算法)
c++·vscode·学习·算法
AA陈超6 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 #06-11:游戏后效果执行
c++·游戏·ue5·游戏引擎·虚幻
天若有情6738 小时前
【python】Python爬虫入门教程:使用requests库
开发语言·爬虫·python·网络爬虫·request
寒水馨9 小时前
Java 17 新特性解析与代码示例
java·开发语言·jdk17·新特性·java17