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. 菜单系统:菜单项和子菜单的统一处理

相关推荐
liu****16 小时前
第15届省赛蓝桥杯大赛C/C++大学B组
开发语言·数据结构·c++·算法·蓝桥杯·acm
charlie11451419116 小时前
嵌入式Linux模块开发——struct module 深度解析:内核模块的核心数据结构
linux·开发语言·数据结构·c
无缘之缘17 小时前
蓝桥杯手把手教你备战(C/C++ B组)(最全面!最贴心!适合小白!)
c语言·c++·算法·蓝桥杯
吴声子夜歌17 小时前
ES6——Symbol详解
开发语言·javascript·es6
星辰徐哥17 小时前
C语言运算符的优先级与结合性详解
c语言·开发语言
HZ·湘怡17 小时前
顺序表 2 续集 c 实现增删查改
c语言·开发语言·顺序表
han_hanker17 小时前
js 加减乘除精度问题2
开发语言·javascript·ecmascript
红目香薰17 小时前
Ascend C 算子:Sigmoid 函数原理深入解析与工程化构建及验证
c语言·开发语言·华为·华为云·昇腾·cann·modelarts
OTWOL17 小时前
C语言操作符终极揭秘:表达式求值秘籍
c语言·开发语言·c++
无巧不成书021817 小时前
Java 21 LTS 高级特性零基础通关:静态导入、项目目录规范、泛型全实战
java·开发语言·标准目录结构·泛型原理·类型安全实现