C++ 组合模式详解

发布于:2025-05-10 ⋅ 阅读:(17) ⋅ 点赞:(0)

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


网站公告

今日签到

点亮在社区的每一天
去签到