07.C++设计模式-组合模式

1. 模式定义

组合模式(Composite Pattern)将对象组合成树形结构 以表示"部分-整体"的层次结构,使客户端对单个对象和组合对象的使用具有一致性

2. 核心结构

<<abstract>>
Component
+operation()
+add(Component)
+remove(Component)
+getChild(int)
Leaf
+operation()
Composite
-children: List<Component>
+operation()
+add(Component)
+remove(Component)
+getChild(int)

3. 应用场景

  • 文件系统:目录包含文件和子目录
  • UI组件:容器控件包含按钮、文本框等
  • 组织结构:部门包含子部门或员工
  • 图形绘制:组合图形由基本图形组成
  • 菜单系统:菜单项可包含子菜单

4. C++代码示例

场景:公司组织架构管理
cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <memory>

// 抽象组件:员工
class Employee {
protected:
    std::string name;
    std::string position;
    
public:
    Employee(std::string name, std::string pos) 
        : name(name), position(pos) {}
    
    virtual ~Employee() = default;
    
    virtual void showInfo(int depth = 0) = 0;
    virtual void add(std::shared_ptr<Employee>) {}
    virtual void remove(std::shared_ptr<Employee>) {}
};

// 叶子节点:普通员工
class OrdinaryEmployee : public Employee {
public:
    OrdinaryEmployee(std::string name, std::string pos) 
        : Employee(name, pos) {}
    
    void showInfo(int depth = 0) override {
        std::string indent(depth * 2, ' ');
        std::cout << indent << "- " << name 
                  << " (" << position << ")" << std::endl;
    }
};

// 组合节点:经理(可管理下属)
class Manager : public Employee {
private:
    std::vector<std::shared_ptr<Employee>> subordinates;
    
public:
    Manager(std::string name, std::string pos) 
        : Employee(name, pos) {}
    
    void add(std::shared_ptr<Employee> employee) override {
        subordinates.push_back(employee);
    }
    
    void remove(std::shared_ptr<Employee> employee) override {
        auto it = std::find(subordinates.begin(), 
                           subordinates.end(), employee);
        if (it != subordinates.end()) {
            subordinates.erase(it);
        }
    }
    
    void showInfo(int depth = 0) override {
        std::string indent(depth * 2, ' ');
        std::cout << indent << "+ " << name 
                  << " (经理 - " << position << ")" << std::endl;
        
        for (auto& emp : subordinates) {
            emp->showInfo(depth + 1);
        }
    }
};

// 客户端代码
int main() {
    // 创建公司组织结构
    auto ceo = std::make_shared<Manager>("张三", "首席执行官");
    
    // 创建部门经理
    auto techManager = std::make_shared<Manager>("李四", "技术总监");
    auto salesManager = std::make_shared<Manager>("王五", "销售总监");
    
    // 创建普通员工
    auto dev1 = std::make_shared<OrdinaryEmployee>("赵六", "高级工程师");
    auto dev2 = std::make_shared<OrdinaryEmployee>("钱七", "前端工程师");
    auto sales1 = std::make_shared<OrdinaryEmployee>("孙八", "销售代表");
    
    // 构建树形结构
    ceo->add(techManager);
    ceo->add(salesManager);
    
    techManager->add(dev1);
    techManager->add(dev2);
    salesManager->add(sales1);
    
    // 显示整个组织结构
    std::cout << "=== 公司组织架构 ===" << std::endl;
    ceo->showInfo();
    
    return 0;
}

5. 结构示意图

CEO 张三
技术总监 李四
销售总监 王五
高级工程师 赵六
前端工程师 钱七
销售代表 孙八

6. 优缺点分析

优点 缺点
高层模块调用简单 可能过度泛化
自由增加新组件 难以限制组件类型
符合开闭原则 设计更复杂

7. 注意事项

  • 透明性 vs 安全性:是否在Component中声明管理操作
  • 父节点引用:便于实现向上遍历
  • 共享资源:注意叶子节点的共享问题
  • 遍历优化:可用缓存提升性能

8. 运行结果

复制代码
=== 公司组织架构 ===
+ 张三 (经理 - 首席执行官)
  + 李四 (经理 - 技术总监)
    - 赵六 (高级工程师)
    - 钱七 (前端工程师)
  + 王五 (经理 - 销售总监)
    - 孙八 (销售代表)

这个示例完美展示了组合模式的核心思想:无论是经理还是普通员工,都通过统一的showInfo()接口调用,客户端无需关心对象的具体类型。

相关推荐
2601_956121977 小时前
二分算法(知识点+题目)
c++·算法
蒙奇·D·路飞-9 小时前
OpenClaw:开源的《合金弹头》精神续作与终极本地部署指南
c++·开源·mfc
董员外9 小时前
RAG 系统进化论(八):Agentic RAG(智能体式 RAG),从回答问题到完成任务
人工智能·后端·设计模式
小星星闪亮登场10 小时前
2026萌新联赛第三场-- (郑州轻工业大学)
数据结构·c++·经验分享·算法·贪心算法·排序算法·深度优先
梓䈑10 小时前
【用 Vibe Coding 实现的 C++17 在线判题系统】前端开发 + Web 自动化测试
前端·c++·ai编程
冻柠檬飞冰走茶11 小时前
PTA基础编程题目集 7-8超速判断(C++语言实现)
开发语言·数据结构·c++·算法
TunerT_TQ11 小时前
Valhalla 静态工程审阅 #018|MMCV 源码证据驱动评测【大厂开源基础设施特辑】
c++·开源·mfc·#计算机视觉·#商汤科技·#openmmlab·#静态源码审计
别动我齐刘海12 小时前
Day6 unitree_G1人形机器人GMR—— MotionInput
c语言·c++·人工智能·学习·机器学习·机器人·github
Henry Zhu12313 小时前
C++17 `weak_from_this` 详解:让对象安全地观察自己
c++
董员外13 小时前
RAG 系统进化论(七):Multimodal RAG(多模态 RAG),当知识存在于表格、图片和页面中
人工智能·后端·设计模式