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()接口调用,客户端无需关心对象的具体类型。