一、概述
在生活中,我们通常希望一些统一的操作,例如当我用杀毒软件扫描该文件夹时,往往不会关心里面有多少文件和子文件夹,我们只需要操作最外层的文件夹进行扫描。
来看一幅图:
这幅图可以对应上例:
1.最顶端组合对象 = 最外层的文件夹
2.叶对象 = 文件夹中的文件
3.子组合对象 = 子文件夹
文件夹与文件可以构成上图中的这种树形结构,客户只需操作最外层的组合对象,忽略内部叶对象与子组合对象,便可以统一执行,完成操作。
由此对象组合成树形结构来表现 "整体和部分" 层次结构,并且组合能让客户以一致的方式处理个别对象以及组合对象,就叫做组合模式。
这个模式的好处是客户仅需与最顶层一个对象交互,便可以完成整个树形系统的统一操作,而且树形结构内部节点上随意删除或者增加对象,对客户是没有影响的。
优点:
1、高层模块调用简单。
2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
二、运用
通过上例,可知组合模式中几个角色:
Component(抽象类):它可以是接口或抽象类,为叶对象和组合对象声明接口。
Leaf(叶对象):它在组合结构中表示叶对象,叶对象没有子节点。
Composite(组合对象):它在组合结构中表示组合对象,组合对象包含子节点,其子节点可以是叶对象,也可以是组合对象。
还是以扫描该文件夹为例,简单介绍一下,Folder 类是组合对象,File 类是叶对象,Floder 中 add 方法提供了构建树形结构的基础方法;组合对象和叶对象必须都含有 scan 方法,才能做到统一执行。
Component (抽象类)
Composite (组合对象)
Leaf (叶对象)
test:
三、应用场景
组合模式如果运用得当,可以大大简化客户的代码。一般来说,组合模式适用于以下这两种情况。
表示对象的部分-整体层次结构。组合模式可以方便地构造一棵树来表示对象的部分-整体结构。特别是我们在开发期间不确定这棵树到底存在多少层次的时候。在树的构造最终完成之后,只需要通过请求树的最顶层对象,便能对整棵树做统一的操作。在组合模式中增加和删除树的节点非常方便,并且符合开放-封闭原则。
客户希望统一对待树中的所有对象。组合模式使客户可以忽略组合对象和叶对象的区别,客户在面对这棵树的时候,不用关心当前正在处理的对象是组合对象还是叶对象,也就不用写一堆 if 、 else 语句来分别处理它们。组合对象和叶对象会各自做自己正确的事情,这是组合模式最重要的能力。