![1ef15c4e297d8f5f22689f7add6ec0b6.png](https://i-blog.csdnimg.cn/blog_migrate/f193a868095ca8b75cfeebe0ccf39c47.jpeg)
我们可以使用简单的对象组合成复杂的对象,而这个复杂对象又可以组合成更大的对象。我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象。客户端代码必须区别对象简单对象和容器对象,而实际上大多数情况下用户认为它们是一样的。对这些类区别使用,使得程序更加复杂。递归使用的时候很麻烦,而我们如何使用递归组合,使得用户不必对这些类进行区别呢?这就要用到我们今天要讲的组合模式。
组合模式,将对象组合成属性结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。有时候又叫做部分-整体模式,它在树型结构中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。组合模式让你可以优化处理递归或分级数据结构。
UML图:
![d40dfb27b079e89aac142b92be8c5bef.png](https://i-blog.csdnimg.cn/blog_migrate/cf6b9b441c1a705fb7b612a4dadafe4a.jpeg)
- 抽象构件角色(component):是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。这个接口可 以用来管理所有的子对象。(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
- 树叶构件角色(Leaf):在组合树中表示叶节点对象,叶节点没有子节点。并在组合中定义图元对象的行为。
- 树枝构件角色(Composite):定义有子部件的那些部件的行为。存储子部件。在Component接口中实现与子部件有关的操作。
- 客户角色(Client):通过component接口操纵组合部件的对象。
举个例子:
![31925c7503aab2d72a6a6af38f8b0b25.png](https://i-blog.csdnimg.cn/blog_migrate/202f13f15073a55593749af6abd03b1d.jpeg)
电脑中的目录结构大家都很清楚,我的电脑下面通常会有C盘、D盘等几个盘,每个盘下会有很多文件夹或文件,这些文件夹下还有有二级文件夹或文件,依次类推,可以组成一个很复杂的目录树,那么如果让你实现这样一个目录结构,该怎么做呢?
#include #include #include using namespace std;//为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为class Component {protected:string name;public:Component(string n) { name = n; }virtual ~Component() {}virtual void Add(Component* c) = 0;virtual void Remove(Component* c) = 0;virtual void Display(int depth) = 0;};//在组合中表示叶节点对象,叶节点没有子节点class Leaf : public Component {public:Leaf(string name) : Component(name) {}void Add(Component* c) {} // 叶节点没有Add功能,但这样做能使接口具备一致性,这就是透明方式,如果不加入Add和Remove方法,那就是安全方式。void Remove(Component* c) {} // 同上void Display(int depth) { cout << name << " " << depth << endl; }};//定义有枝节点行为,用来存储子部件class Composite : public Component{private:list children;public:Composite(string name) : Component(name) {}void Add(Component* c) { children.push_back(c); }void Remove(Component* c) { children.remove(c); }void Display(int depth) {cout << name << " " << depth << endl;for (auto c = children.begin(); c != children.end(); c++) {(*c)->Display(depth + 1);}}};//客户端实现代码int main() {Composite* root = new Composite("我的电脑");Composite* comp = new Composite("C盘");comp->Add(new Leaf("新建文件夹1"));comp->Add(new Leaf("新建文件夹2"));root->Add(comp);Composite* comp2 = new Composite("D盘");Composite* comp3 = new Composite("相册");comp2->Add(comp3);comp3->Add(new Leaf("图片1"));comp3->Add(new Leaf("图片2"));root->Add(comp2);root->Display(1);return 0;}
运行结果:
我的电脑 1C盘 2新建文件夹1 3新建文件夹2 3D盘 2相册 3图片1 4图片2 4
![fa2da48ac3be6e5b785e38bac7759942.png](https://i-blog.csdnimg.cn/blog_migrate/b50718a2d96a61c7d48a578d7944ed75.jpeg)