模式概述
在开发中,我们经常可能要递归构建树状的组合结构,如类似以下结构,Composite模式则提供了很好的解决方案。当然也可以直接使用三方库tree,官方网址http://tree.phi-sci.com/。可作为STL的扩展库使用。
最经典的例子莫过于计算机文件系统了。在文件系统中有文件夹的概念,文件夹里面既可以放入文件也可以放入文件夹,但是文件中却不能放入任何东西。文件夹和文件构成了一种递归结构和容器结构。
虽然文件夹和文件是不同的对象,但是他们都可以被放入到文件夹里,所以一定意义上,文件夹和文件又可以看作是同一种类型的对象,所以我们可以把文件夹和文件统称为目录条目,(directory entry).在这个视角下,文件和文件夹是同一种对象。
所以,我们可以将文件夹和文件都看作是目录的条目,将容器和内容作为同一种东西看待,可以方便我们递归的处理问题,在容器中既可以放入容器,又可以放入内容,然后在小容器中,又可以继续放入容器和内容,这样就构成了容器结构和递归结构。
这就引出了我们本文所要讨论的composite模式,也就是组合模式,组合模式就是用于创造出这样的容器结构的。是容器和内容具有一致性,可以进行递归操作。如下:
Composite模式由以下角色组成
- 抽象构件(Component)角色: 这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。合成对象通常把它所包含的子对象当做类型为Component的对象。在安全式的合成模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝构件对象给出。
- 树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
- 树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法。
模式结构
透明模式
安全模式
模式讨论
合成模式可以不提供管理父对象的管理方法,但是合成模式必须在合适的地方管理子对象的管理方法。在什么地方声明子对象的管理方法,例如add()、remove()、getChild()等方法。根据提供管理方法的位置不同分为两种:透明方式和安全方式。
安全模式的合成模式
- 优点是是一种安全的做法,因为树叶节点没有add()等方法,因此客户端对树叶节点调用这些方法时编译期间就不会通过。
- 缺点是不够透明,因为树叶类和合成类将具有不同的接口,而且客户端调用相关方法需要区分树叶节点和数枝节点。
透明模式的合成模式
与安全模式不同的是,透明模式的合成模式要求所有的具体构件类,无论是叶子节点还是树叶节点,均符合一个固定的接口,也就是在所有节点都具备相应方法。只不过在叶子节点的不相干方法中不做任何操作。
- 优点所有的构件类都有相同的接口,在客户端看来,树叶类对象与数枝对象的区别起码在接口层次上消失了。
- 缺点是不安全,因为树叶节点和数枝节点在本质上是有区别的。树叶对象不可能有子节点的存在。因此调用树叶节点的方法容易引起运行时错误。
模式实现
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后的笔记潇汀会尽量详细讲解一些相关知识的,希望大家继续关注我的博客。
本节笔记到这里就结束了。
潇汀一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。
编程开发的路很长很长,非常希望能和大家一起交流,共同学习,共同进步。
如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。
最后,谢谢你们一直的支持~~~
C++完整个代码示例(代码在VS2017下测试可运行)
代码及相关资料下载地址:
https://gitee.com/arvinxt/DesignPattern