• 由查找算法工程的类图分析组合模式


    关键字:算法工程的类图,架构分析,设计模式,组合模式

    首先,上一个我刚完成的针对上一篇Knowledge_SPA——精研查找算法文中使用的工程,所画的类图,由此来分析它的架构。如下图所示:

    image

    我们这个工程中使用到了很多设计模式,考虑到了不少设计原则,这一篇又回到了设计模式的学习路线,那么可以勉强使用这个工程来分析一下组合模式。

    组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。

    分角色

    如果要使用组合模式,首先要将你的系统区分出几个角色:

    • 主干
    • 叶子结点
    • 树枝

    这三个角色是什么意思呢?
    从上面定义可知,对象之间通过组合关系形成树形结构。那么从这个树形结构中去将这三个角色区分出来并不难。

    我们结合算法的工程来举例分析,由于还有其他架构在里面,这里我们只分析ST这一支。

    • 主干是ST
    • 叶子结点是SequentialSearchST, BinarySearchST, BST, RedBlackBST, ChainHashST, ProbeHashST
    • 树枝是SFunction

    角色的活

    角色区分完毕以后,要给他们安排具体任务,

    • 主干就是最终提供给客户端调用的类
    • 叶子结点是继承于主干,他是干具体活,实现具体操作的类
    • 树枝是用来存储叶子结点,同时也是继承于主干

    抛砖

    从这里我们可以看出不同,我们的查找算法工程(如上图)是呈现三层结构,

    ST -> SFunction -> XXXST

    而组合模式的意思是什么?

    ST -> SFunction -> XXXST; ST->XXXST

    所以,通过查找算法工程的类图,我们抛砖引玉,引出了真正的组合模式,能够看出来么,组合模式的核心思想是在三层基础上,仍旧保持主干和叶子结点的关联关系,这有什么好处呢?

    组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素。

    换句话说,就是客户端操作的主干类,这个主干类可以注入叶子结点和树枝,叶子结点就是简单元素,树枝因为它本身包含很多叶子结点,因此它是复杂元素。这样以来,客户端实际在操作叶子结点和树枝时,所付出的“辛苦”是相同的。这里再用算法工程的类图来表示就不合适了。

    引玉

    业界常见的例子是操作系统里面的文件管理器,我们也来画一个。
    image

    这是组合模式最终的版本的样子,下面来解释一下上面的类图。

    • AbstractFile

      主干类,也叫Component,提供给客户端直接调用的对象,它是目前所有对象的基类,定义了operation方法。

    • XXXFile

      叶子结点,具体文件的具体类型,继承了AbstractFile类并实现了不同类型文件的具体的operation方法内容,同时它也是Folder对象的一份子,与Folder对象是多对一的关系。

    • Folder

      组合模式的核心对象。首先它也继承了AbstractFile类,该有的继承方法和属性都与XXXFile一样,然而他的不同之处在于它有一个成员属性是一个存储基类的列表,相应地,它还拥有着对这个列表的增删改查的方法用来堵这个列表进行调整。最后,与XXXFile实现的operation方法的内容不同的是,Folder实现的operation方法是遍历当前列表并依次调用他们内部具体的operation方法。

    组合模式的英文全称为Composite Pattern,而Folder所代表的对象即上面说的树枝,英文也被称为Composite。

    组合模式总结

    组合模式理解起来非常简单,也很巧妙,但是要注意在客户端要调整Composite里的列表时,要直接调用Composite对象的方法,而不是统一只有一个Component对象暴露在客户端。这一点确实有损面向对象的封装性,但是却避免了将这些列表操作方法放入Component类中,让叶子结点也去实现这些跟他们毫无关系的方法,并且在运行时一旦有程序调用了叶子结点的这些方法会引发错乱,相比于此,在客户端暴露出Composite对象是代价比较小的方式。

    • 适用场景

    在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们,那就选择使用组合模式吧。

  • 相关阅读:
    firewalld防火墙
    MariaDB
    if,for,while
    自定义带图标input样式
    display:inline-block 和 float 水平排列区别?
    css中块元素和行内元素区别
    margin-top 为什么会影响父元素的 margin-top
    vertical-align 的理解
    什么是HTTP协议?
    Grunt 自动编译 Less 文件配置
  • 原文地址:https://www.cnblogs.com/Evsward/p/Composite.html
Copyright © 2020-2023  润新知