1.概述
组合模式又叫部分整体模式属于结构型模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
2.结构
- 组件(Component):定义了组合中所有对象的通用接口,可以是抽象类或接口。它声明了用于访问和管理子组件的方法,包括添加、删除、获取子组件等。
- 叶子节点(Leaf):表示组合中的叶子节点对象,叶子节点没有子节点。它实现了组件接口的方法,但通常不包含子组件。
- 复合节点(Composite):表示组合中的复合对象,复合节点可以包含子节点,可以是叶子节点,也可以是其他复合节点。它实现了组件接口的方法,包括管理子组件的方法。
- 客户端(Client):通过组件接口与组合结构进行交互,客户端不需要区分叶子节点和复合节点,可以一致地对待整体和部分。
3.实现
3.1 实例类比
以电脑文件系统为例,其中有两种类型的文件:文本文件和文件夹。文本文件是叶子节点,文件夹是组合节点,可以包含其他文件。
类体如下:
3.2 具体实现
#include <iostream>
#include <string>
#include<vector>using namespace std;
/*** Component抽象类,表示目录条目(文件+文件夹)的抽象类**/
class Component {public:virtual string getName() = 0; //获取文件名virtual int getSize() = 0; //获取文件大小//添加文件夹或文件virtual Component* add(Component* entry) = 0;//显示指定目录下的所有信息virtual void printList(string prefix) {};
};/*** File类 表示文件**/
class File :public Component {private:string name_; //文件名int size; //文件大小public:File(string name, int size) {this->name_ = name;this->size = size;}string getName() {return name_;}int getSize() {return size;}Component* add(Component* entry) {return nullptr;}void printList(string prefix) {cout << prefix + "/" << name_ << endl;}};/*** Directory表示文件夹**/
class Directory :public Component {//文件的名字
private:string name_;//文件夹与文件的集合vector<Component*> directory;public://构造函数Directory(string name) {this->name_ = name;}//获取文件名称string getName() {return this->name_;}int getSize() {int size = 0;//遍历或者去文件大小for (auto it : directory) {size += it->getSize();}return size;}Component* add(Component* entry) {directory.push_back(entry);return this;}//显示目录void printList(string prefix) {cout << prefix << "/" << name_ << endl;for (auto it : directory) {it->printList(prefix + "/" + name_);}}
};int main()
{//根节点Directory *rootDir = new Directory("root");//树枝节点Directory *binDir = new Directory("bin");//向bin目录中添加叶子节点binDir->add(new File("test1", 1024));binDir->add(new File("test2", 2048));Directory *nginxlDir = new Directory("ngnix");Directory *confDir = new Directory("conf");nginxlDir->add(confDir);confDir->add(new File("nginx.conf", 30));rootDir->add(binDir);rootDir->add(nginxlDir);rootDir->printList("");return 0;
}
3.3运行结果
4.状态设计模式优缺点
优点:
- 可以将对象组合成树形结构,表示整体-部分的层次关系。
- 可以统一处理单个对象和对象组合,简化了客户端的代码逻辑,提高了系统的可复用性。
- 可以遵循开闭原则,扩展性高,增加新的节点类型时不需要修改原有代码。
缺点
对于功能差异较大的类, 提供公共接口或许会有困难。 在特定情况下, 你需要过度一般化组件接口, 使其变得令人难以理解。
5 应用场景
- 当需要表示一个对象整体与部分的层次结构时,可以使用组合模式来实现树形结构。例如,文件系统中的文件与文件夹、组织机构中的部门与员工、商品分类中的类别与商品等。
- 当需要统一处理单个对象和对象组合时,可以使用组合模式来实现多态性。例如,图形界面中的简单控件与容器控件、菜单系统中的菜单项与子菜单、报表系统中的单元格与表格等。
- 当需要将对象的创建和使用分离时,可以使用组合模式来实现依赖注入。例如,Spring框架中的Bean对象与BeanFactory对象、测试框架中的测试用例与测试套件等。