上篇:

【学习设计模式10】分离抽象与实现——桥接模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式9】兼容扩展坞—适配器模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式8】组装流水线——建造者模式_Aiky哇的博客-CSDN博客上篇:【学习设计模式7】复制粘贴就得了——原型模式_Aiky哇的博客-CSDN博客那么有没有一种方法可以名正言顺的复制粘贴呢?当然有了,那就是原型模式。原型模式也叫克隆模式。https://aikysay.blog.csdn.net/article/details/123407658建造者模式的定义建造者模式的使用流程建造者模式的适用场景建造者模...https://aikysay.blog.csdn.net/article/details/124807449

在使用递归的时候,经常会遇到一个问题,对于叶子结点和非叶子节点,往往需要两套不同的逻辑来执行。区别对待的后果就是代码的混杂。

那么有没有一种方法能够使树中各个节点的处理达到统一呢?组合模式可以满足。

组合模式的定义

组合模式(Composite Pattern):组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式。

简单来说就是,使叶子节点和非叶子节点能够调用相同的接口,实现相同的功能,但是叶子节点和非叶子节点的接口实现不同。

组合模式的UML

  • Component(抽象构件):它可以是接口或抽象类,为叶子构件和容器构件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。
  • Leaf(叶子构件):它在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。
  • Composite(容器构件):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。

这么理解,Leaf就是叶子结点,Composite就是非叶子节点。

他们会实现相同的接口,接口由Component来定义。非叶子节点和叶子节点必须都实现operation行为,对于其他方法,叶子节点可以不管。

组合模式的举例思考 

比如说,现在要考虑一种场景,文件夹中包含文件。现在要遍历这个文件夹。

如果不考虑组合模式,使用普通的设计思路:

type dirOrFile struct{isDir boolname stringchildren []dirOrFile//...
}

会设计出这样一个类,其中使用一个bool型来表示这个对象是文件夹还是文件。
这样虽然看起来很简单,实际维护起来会很麻烦。每个方法都需要根据bool型来确定是文件夹还是文件,再根据对象的类型来选择方法。这样也不满足单一职责原则。

考虑组合模式的设计思路:

type Component interface{GetName() stringGetChildren() []Component
}type Dir struct{name stringchildren []Component
}func(d *Dir) GetName() string{return d.name
}func(d *Dir) GetChildren() string{return d.children
}type File struct{name string
}func(d *File) GetName() string{return d.name
}func(d *File) GetChildren() string{return nil
}

这样就能很好的将文件夹类型和文件类型分开处理。

每个类型不会包含多余的变量,满足单一职责原则。每个类型还可以单独扩展,不会对其他类型造成麻烦,甚至可以自由扩展出其他节点类型,符合开闭原则。

在遍历的时候也消除了两个类调用上的区别,可以作为相同类型的对象来处理。

组合模式的优缺点与适用场景

主要优点

  1. 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。
  2. 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。
  3. 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
  4. 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

主要缺点

  1. 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
  2. 在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。

适用场景

  1. 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。
  2. 在一个使用面向对象语言开发的系统中需要处理一个树形结构。
  3. 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。

总之对于树形结构,部分-整体的场景都是非常实用的。

参考资料 

树形结构的处理——组合模式(二)_LoveLion的博客-CSDN博客

Go设计模式(16)-组合模式_程序员麻辣烫的博客-CSDN博客

组合模式 | 菜鸟教程

树形结构的处理——组合模式(五)_LoveLion的博客-CSDN博客

【学习设计模式11】树形处理——组合模式相关推荐

  1. 设计模式学习笔记(十一)-组合模式

    树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题,组合模式通过一种巧妙的设计方案使得 ...

  2. 设计模式十二之组合模式

    设计模式十二之组合模式 1. 模式的定义与特点 1.1 模式的定义 1.2 模式的特点 1.3 模式的使用场景 2. 模式的结构与实现 2.1 模式的结构 2.2 模式的实现 3. 模式在开源软件中的 ...

  3. Java设计模式(8)组合模式(Composite模式)

    Composite定义:将对象以树形结构组织起来,以达成"部分-整体" 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Compo ...

  4. 设计模式之禅【组合模式】

    真刀实枪之组合模式 从公司的人事架构谈起吧 公司的组织架构 从上图中可以分析出: 有分支的节点(树枝节点) 无分支的节点(叶子节点) 根节点(无父节点) 有了树状结构图,再看看类图长啥样吧! 这个类图 ...

  5. 设计模式的理解:组合模式 (Composite)

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...

  6. 设计模式08: Composite 组合模式(结构型模式)

    Composite 组合模式(结构型模式) 对象容器的问题 在面向对象系统中,我们常会遇到一类具有"容器"特征的对象--即他们在充当对象的同时,又是其他对象的容器. public ...

  7. 大战设计模式【13】—— 组合模式

    组合模式(Composite) 设计模式使用的例子https://github.com/LinkinStars/DesignPatternsAllExample 一.定义 组合多个对象形成树形结构以表 ...

  8. 设计模式笔记九:组合模式

    原文:http://www.runoob.com/design-pattern/ 少许个人理解,如有错误请指出.欢迎一起讨论. 组合模式(Composite Pattern) 又叫部分整体模式,是用于 ...

  9. 设计模式9——迭代器和组合模式

    如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了 代码地址:https://github.com/keer123456789/MY_STUDY_LIFE/tree/master/src/main/ja ...

最新文章

  1. SAP MM 公司间STO里外向交货单与内向交货单里序列号对应关系
  2. walletconnect
  3. mxnet基础到提高(5)-- 卷积神经网络基础(1)
  4. CRDT——解决最终一致问题的利器
  5. 如何使用腾讯云提供的虚拟主机
  6. 面条html5,使用 babel 全家桶模块化古老的面条代码
  7. C语言中的数组的使用——混乱的内存管理
  8. 、简述global关键字的作用_GLOBAL和$GLOBALS[]的讲解
  9. xmldocument的使用
  10. mysql传参为数组,将数组传递给MySQL存储例程
  11. PHP魔术方法和魔法变量详解
  12. React Native : AsyncStorage 存储
  13. 第九届蓝桥杯JavaA组省赛真题
  14. java-合并两个有序链表
  15. 微信小程序的简单使用(做一个阻抗计算器)
  16. QT设置窗体标题及背景颜色
  17. Memwatch简介
  18. g++/gcc compile_options
  19. axios 之 post请求参数格式不正确得问题
  20. 对学生公寓部建议和意见_部门管理建议和意见 宿舍管理意见和建议

热门文章

  1. SQL Server数据控制(Grant和Revoke)——架构
  2. 计算机图形学---DDA直线画法c#实现
  3. python中global的意思_python中global是什么意思?
  4. Oracle_字段拼接_逗号_单引号
  5. 庄子·内篇·齐物论第二(郭象注)
  6. (PHP)将别人女朋友照片转成动漫头像(详细)
  7. 细讲sklearn决策树后剪枝(带例子)
  8. Rsync文件同步软件在CentOS Linux 8下的安装与配置(DNF/YUM安装方式)
  9. 解决 命令行程序 中文英文不对齐的情况
  10. 拼多多放心推系统必须知道的规则!千万别错过