前言
Composite(组合模式)是一种管理树形结构的抽象方式。其是将对象组合成树形结构,从而构成表示 “部分 - 整体” 的层次结构。这种层次关系在日产生活中十分常见。如在公司组织关系中,可能分为部门与人,其中人属于部门,有的人有下属,有的人没有下属。假如将部门、人等都抽象成为一个节点(不用关心当前节点是部门还是人,两者有公共的基类),这样的话公司的组织架构就十分清晰,而且某个部门下有多少人、财务数据等这些数据也容易统计。除了公司外,在操作系统中也普遍应用,其中的文件夹与文件就是典型的树状结构,为了保证扩展性与可维护性,在设计时可以将文件夹与文件抽象为文件,这样每个节点都拥有相同的方法添加、删除、查找子元素,无需要关心当前节点的具体类型。下面我们予以详细的介绍
一、组合模式(Composite 模式)
Composite 和 Leaf需要实现部分同样的接口,其中Leaf(文件或者人)类需要实现Operation的功能,其他的不需要实现,而Composite(文件夹或者部门)类除了要实现Operation功能外,还需实现添加、删除、查询等功能。因此Composite 和 Leaf有着一个共同的父类——Component。这样,两者都可以通过Component*来统一进行调用了。UML图如下:
二、具体源码
1.Composite.h
代码如下(示例):
#pragma once
#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_
#include <iostream>
#include <algorithm>
#include <vector>
class Component
{
public:
Component();
virtual ~Component();
public:
//Leaf和Composite统一的接口
virtual void Operation() = 0;
virtual void Add(const Component&);
virtual void Remove(const Component&);
virtual Component* GetChild(int);
protected:
private:
};
class Composite :public Component
{
public:
Composite();
~Composite();
public:
void Operation();
void Add(Component* com);
void Remove(Component* com);
Component* GetChild(int index);
protected:
private:
//存储树结构下面相关数据,例如,一个文件夹下面肯定还有文件夹以及文件
std::vector<Component*> comVec;
};
class Leaf :public Component
{
public:
Leaf();
~Leaf();
//Leaf就相当于树结构的最后一层,无需添加、删除、查询等功能
void Operation();
protected:
private:
};
#endif //~_COMPOSITE_H_
2.Composite.cpp
代码如下(示例):
#include "Composite.h"
Component::Component()
{
}
Component::~Component()
{
}
void Component::Add(const Component& com)
{
}
Component* Component::GetChild(int index)
{
return 0;
}
void Component::Remove(const Component& com)
{
}
Composite::Composite()
{
//当然,内部成员comVec也可以在构造函数内进行初始化,具体的就不列出了
}
Composite::~Composite()
{
}
void Composite::Operation()
{
std::vector<Component*>::iterator comIter = comVec.begin();
for (; comIter != comVec.end(); comIter++)
{
(*comIter)->Operation();
}
}
void Composite::Add(Component* com)
{
comVec.push_back(com);
}
void Composite::Remove(Component* com)
{
std::remove(comVec.begin(),comVec.end(),com);
}
Component* Composite::GetChild(int index)
{
return comVec[index];
}
Leaf::Leaf()
{
}
Leaf::~Leaf()
{
}
void Leaf::Operation()
{
std::cout << "Leaf operation....." << std::endl;
}
3.main.cpp
代码如下(示例):
#include "Composite.h"
int main(int argc, char* argv[])
{
Leaf* l = new Leaf();
l->Operation();
Composite* com = new Composite();
com->Add(l);
com->Operation();
Component* ll = com->GetChild(0);
ll->Operation();
return 0;
}
三、运行结果
Composite 模式运行结果如下:
总结
Composite 模式在实现中有一个问题就是要提供对于子节点(Leaf)的管理策略,这里使用的是 STL 中的 vector,可以提供其他的实现方式,如数组、链表、Hash 表等。
Composite 模式可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了代码开发;而且更容易在组合体内加入新的对象,满足“开闭原则”;但是,其层次结构较复杂,需要花更多时间理清类之间的层次关系,而且不容易用继承的方法来增加构件的新功能。
Composite 模式通过和 Decorator 模式有着类似的结构图,但是 Composite 模式旨在构造类,而 Decorator 模式重在不生成子类即可给对象添加职责。Decorator 模式重在修饰,而Composite 模式重在表示。
本文参考《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》,对内容进行整理,方便大家学习。如想学习详细内容,请参考此书。