目录
- 一、概念
- 二、类图详解
- 三、组合模式实现步骤
- 四、代码实现
- 4.1 Component类
- 4.2 Composite类
- 4.3 Leaf类
- 4.4 测试
- 五、扩展
一、概念
- 组合模式又叫
整体--部分模式
- 组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分
- 可以一致地对待容器对象和叶子对象。
- 它使树型结构的问题中,模糊了
简单元素
和复杂元素
的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
二、类图详解

- 包含一个抽象组件类
Component
、叶子结点类Leaf
和组件集合类Composite
。 - 抽象组件类:组合中的对象声明接口,实现所有类共有接口的行为。声明用于访问和管理Component的子部件的接口。
- 叶子结点:叶节点对象,就是终端独立结点,不能
add
或Remove
其它组件。 - 组件集合类:实现Component的相关操作,可以继续包含组件集合类和叶子结点。
Composite
与Component
类形成迭代关联关系。
三、组合模式实现步骤
- 定义抽象组件接口
- 实现叶子节点类,实现抽象组件类的接口。
- 实现组件集合类,实现抽象组件类的接口。
- 定义环境类,将叶子节点和组件集合加入根组件集合。
四、代码实现
- 生成目录树结构,目录里面可以再放目录或文件
- 最终的输出如下

4.1 Component类
#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类
#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类
#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 测试
#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;
}
五、扩展
- 设计一个饭店的菜单
- 可以再包含一个菜单或者菜单项
- 类图如下

- 菜单项图结构如下

- 代码部分请参阅 https://gitee.com/piglittle/design_patterns中的
Head_First_Design_Partterns
解决方案下的 composite_pattern
项目