目录
组合模式(Composite Pattern)是一种结构型设计模式,它允许你组合对象形成树形结构来表示“部分-整体”的层次结构。组合模式让客户端能够一致地处理单个对象和组合对象,而无需关心它们的具体类型。这样,客户端代码可以透明地使用组合结构中的单个对象或整个组合。
组合模式的关键概念
- Component(组件)接口:定义了所有节点(叶子节点和分支节点)共有的操作。
- Leaf(叶子)类:实现Component接口,代表树形结构中的叶子节点。
- Composite(组合)类:也实现了Component接口,代表树形结构中的分支节点,它可以包含子Component对象。
- Client(客户端):通过Component接口来操作单个对象或组合对象。
组合模式的优点
- 统一接口:客户端可以一致地对待单个对象和组合对象。
- 递归结构:可以很容易地构建递归结构。
- 灵活扩展:容易添加新的组件类型而不修改现有代码。
组合模式的缺点
- 过度使用:如果不需要层次结构,那么使用组合模式可能会引入不必要的复杂性。
- 复杂度增加:随着层次结构的加深,维护和理解代码可能会变得更加困难。
例子:文件系统
假设我们需要实现一个文件系统,其中包含文件夹和文件。文件夹可以包含其他文件夹和文件,而文件则不可再分割。
步骤 1:定义Component接口
c
深色版本
1#include <iostream>
2#include <vector>
3
4class Component {
5public:
6 virtual ~Component() {}
7 virtual void add(Component *component) = 0;
8 virtual void remove(Component *component) = 0;
9 virtual void display(int depth) = 0;
10};
11
12class Leaf : public Component {
13public:
14 Leaf(const std::string &name) : name(name) {}
15 void add(Component *component) override {
16 std::cout << "Cannot add to a leaf component." << std::endl;
17 }
18 void remove(Component *component) override {
19 std::cout << "Cannot remove from a leaf component." << std::endl;
20 }
21 void display(int depth) override {
22 printTabs(depth);
23 std::cout << "Leaf: " << name << std::endl;
24 }
25private:
26 void printTabs(int tabs) {
27 for (int i = 0; i < tabs; ++i) {
28 std::cout << "\t";
29 }
30 }
31 std::string name;
32};
33
34class Composite : public Component {
35public:
36 Composite(const std::string &name) : name(name) {}
37 void add(Component *component) override {
38 children.push_back(component);
39 }
40 void remove(Component *component) override {
41 children.erase(std::remove(children.begin(), children.end(), component), children.end());
42 }
43 void display(int depth) override {
44 printTabs(depth);
45 std::cout << "Composite: " << name << std::endl;
46 for (auto &child : children) {
47 child->display(depth + 1);
48 }
49 }
50private:
51 void printTabs(int tabs) {
52 for (int i = 0; i < tabs; ++i) {
53 std::cout << "\t";
54 }
55 }
56 std::string name;
57 std::vector<Component*> children;
58};
步骤 2:创建组合结构
c
深色版本
1int main() {
2 Composite *root = new Composite("Root Folder");
3
4 Composite *subFolder1 = new Composite("Sub Folder 1");
5 subFolder1->add(new Leaf("Document A"));
6 subFolder1->add(new Leaf("Document B"));
7
8 Composite *subFolder2 = new Composite("Sub Folder 2");
9 subFolder2->add(new Leaf("Document C"));
10
11 root->add(subFolder1);
12 root->add(subFolder2);
13 root->add(new Leaf("Document D"));
14
15 root->display(0);
16
17 delete root;
18 return 0;
19}
输出结果
plaintext
深色版本
1Composite: Root Folder
2 Composite: Sub Folder 1
3 Leaf: Document A
4 Leaf: Document B
5 Composite: Sub Folder 2
6 Leaf: Document C
7 Leaf: Document D
说明
在这个例子中:
Component
是抽象基类,定义了所有节点共有的方法。Leaf
和Composite
分别代表叶子节点和组合节点。Composite
类可以包含多个Component
对象,并提供了add
和remove
方法来管理子节点。display
方法用于显示节点及其子节点的信息,客户端可以通过这个方法来遍历整个组合结构。
这个例子展示了如何使用组合模式来组织和操作文件系统中的文件夹和文件。通过这种模式,我们可以轻松地扩展系统,添加更多的功能,如搜索、排序等,而不改变现有的代码结构。