目录
一、概念
- 组合模式又叫
整体--部分模式
- 组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分
- 可以一致地对待容器对象和叶子对象。
- 它使树型结构的问题中,模糊了
简单元素
和复杂元素
的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
二、类图详解
- 包含一个抽象组件类
Component
、叶子结点类Leaf
和组件集合类Composite
。
- 抽象组件类:组合中的对象声明接口,实现所有类共有接口的行为。声明用于访问和管理Component的子部件的接口。
- 叶子结点:叶节点对象,就是终端独立结点,不能
add
或Remove
其它组件。
- 组件集合类:实现Component的相关操作,可以继续包含组件集合类和叶子结点。
Composite
与Component
类形成迭代关联关系。
三、组合模式实现步骤
- 定义抽象组件接口
- 实现叶子节点类,实现抽象组件类的接口。
- 实现组件集合类,实现抽象组件类的接口。
- 定义环境类,将叶子节点和组件集合加入根组件集合。
四、代码实现
- 生成目录树结构,目录里面可以再放目录或文件
- 最终的输出如下

4.1 Component类
cpp
复制代码
#pragma once
#include <iostream>
class Component
{
public:
std::string name; //叶子结点和组件结点都有名字和类型
bool m_isLeaf; //是否是叶子结点(暂时没用)
Component(const std::string& name, bool isLeaf)
{
this->name = name;
this->m_isLeaf = isLeaf;
}
virtual void Add(Component* c) = 0;
virtual void Remove(Component* c) = 0;
virtual void Display(int depth) = 0;
bool isLeaf() const
{
return this->m_isLeaf;
}
};
4.2 Composite类
cpp
复制代码
#pragma once
#include <iostream>
#include <list>
#include "Component.h"
class Composite: public Component
{
private:
std::list<Component*> m_component;
public:
Composite(const std::string& name) : Component(name, false)
{
}
void Add(Component* c) override
{
m_component.push_back(c);
}
void Remove(Component* c) override
{
m_component.remove(c);
}
void Display(int depth) override
{
std::cout << std::string(depth, '-') << name << std::endl;
for (auto item : m_component)
{
item->Display(depth + 2);
}
}
};
4.3 Leaf类
cpp
复制代码
#pragma once
#include <iostream>
#include "Component.h"
class Leaf: public Component
{
public:
Leaf(const std::string& name): Component(name, true)
{
}
void Add(Component* c) override
{
std::cout << "Can't add component to leaf." << std::endl;
}
void Remove(Component* c) override
{
std::cout << "Can't remove component to leaf." << std::endl;
}
void Display(int depth) override
{
std::cout << std::string(depth, '-') << name << std::endl;
}
};
4.4 测试
cpp
复制代码
#include "Leaf.h"
#include "Composite.h"
class Client
{
private:
Component* com;
public:
Client(Component* obj)
{
com = obj;
}
void display(int n)
{
com->Display(n);
}
};
int main()
{
Component* root = new Composite("根目录");
root->Add(new Leaf("根目录下的文件A"));
root->Add(new Leaf("根目录下的文件B"));
Component* dir1 = new Composite("根目录下的文件夹FA");
dir1->Add(new Leaf("文件夹FA下的文件A"));
dir1->Add(new Leaf("文件夹FA下的文件B"));
root->Add(dir1);
Component* dir2 = new Composite("根目录FA下的文件夹FAX");
dir2->Add(new Leaf("文件夹FAX下的文件A"));
dir2->Add(new Leaf("文件夹FAX下的文件B"));
dir1->Add(dir2);
root->Add(new Leaf("根目录下的文件C"));
root->Add(new Leaf("根目录下的文件D"));
Client c(root);
c.display(1);
return 0;
}
五、扩展