组合模式

组合模式:

  掌握组合模式的 透明写法 和 安全写法

  一个国家会设立很多机构,如三省六部,这些机构下又又很多小的组织。他们共同管理这个国家

  一个公司下面有很多部门,每个部门下面又有很多小组。这就是组合模式

组合模式:Composite Pattern

  又叫 整体-部分模式,整体和个体共性,全部放到一个抽象中统一处理

  宗旨:通过将单个对象(叶子节点)和 组合对象(树枝节点)用相同的接口进行表示,使得客户对 单个对象 和 组合对象 的使用具有一致性

  属于结构型模式


  组合关系 和 聚合关系 的区别:

    组合关系:在古代,皇帝有三宫六院,贵妃很多,但是每个妃嫔只属于皇帝(具有相同的生命周期)

    聚合关系:一个老师有很多学生,但是每一个学生又属于多个老师(具有不同的生命周期)

  组合模式一般用来描述 整理 和 部分 的关系,他将对象组织到 树形结构 中,最顶层的节点为根节点,根节点 下面可以包含 树枝节点 和 叶子节点,树枝节点 下面又可以包含 树枝节点 和叶子节点


  根节点 和 树枝节点 本质上是同一种数据类型,可以作为容器使用

  叶子节点 和 树枝节点 再语义上不属于同一种类型,但是在组合模式中,会把 叶子节点 和 树枝节点 认为是同一种数据类型(用同一接口定义),让他们具备一致行为。

  所以,在组合模式中,整个树形结构中的对象都是同一种类型,带来的好处就是 客户端无需辨别 叶子节点 还是 树枝节点,而是可以直接进行操作,给客户使用带来极大的便利


组合模式包含3个角色:

  抽象根节点(Component): 定义系统各层次对象的 共有方法 和 共有属性,可以预先定义默认行为和属性

  树枝节点(Composite): 定义树枝节点的行为,存储子节点,组合树枝节点 和 叶子节点 形成一个树形结构

  叶子节点(Leaf): 叶子节点对象,其再无分支,是系统层次遍历的最小单位


  组合模式 在代码实现上,有两种不同方式,透明组合模式 和 安全组合模式


应用场景:

  希望客户端可以忽略 组合对象 和 单个对象的差异时

  对象层次具备 整体 和 部分,成树形结构

  生活中那个的组合模式:
    树形菜单、操作系统目录结构、公司组织架构等


  透明写法和安全写法有啥区别?
    透明:所有都写在抽象中
    安全:只有具有共性的内容写在抽象中

  透明组合模式的写法:

    透明组合模式 是把所有公共方法都定义在 Component 中,这样做的好处是 客户端无需分辨是 叶子节点(Leaf)还是 树枝节点(Composite), 他们具备完全一致的接口。
    vip.pattern.composite.general.transparent

  业务实例:

    以课程学习为例,设计一个课程的关系结构

    比如有 Java入门课程、人工只能课程、Java设计模式、源码分析等,而 Java设计模式、源码分析 又属于 Java架构师系列课程包,每个课程的定价都不一样。

    但是,这些课程不论怎么组合,都有一些共性,而且是整体与部分的关系,可以用组合模式来设计。

    创建顶层的抽象组件 CourseComponent 类, 把所有可能用到的方法都定义到抽象类中

    创建课程 Course 类,定义课程基础信息

    创建课程包 CoursePackage 类,具体组合方法的实现

    vip.pattern.composite.demo.transparent

  透明组合模式的缺点是:叶子节点(Leaf)会继承得到一些它所不需要的方法,违背了接口隔离原则


安全组合模式的写法:

  安全组合模式 是只规定系统各个层次的最基础的一致行为,而把组合(树叶节点)本身的方法(管理子类对象的添加、删除)放到自身当中。

  vip.pattern.composite.general.safe

  业务实例:

    电脑的文件系统,典型的树形结构,目录包含文件夹和文件,文件夹里又可以包含文件夹和文件

    创建顶层的抽象组件 Directory 类,

    创建 File 类,

    创建 Folder 类,

    vip.pattern.composite.demo.safe

  安全组合模式的好处是:接口定义职责清晰,符合 单例职责原则 和 接口隔离原则
  缺点是:客户需要区分数据类型,树枝节点(Composite) 和 叶子节点(Leaf),这样才能正确处理各个层次的操作,客户端无法依赖抽象,违背依赖倒置原则

组合对象 和 被组合对象 都应该又统一的接口实现 或者 统一的抽象父类。


组合模式一定是树形接口吗?
  不一定,不管你是整体还是个体,都要想办法用同一种方法来操作

组合模式至少有一个共性


源码中的体现:

  HashMap 的 putAll() 方法

    putAll() 方法传入的是 Map 对象,Map 就是一个抽象构件,而 HashMap 是一个中间构件,HashMap 中的 Node 节点就是 叶子节点

  ArrayList 的 addAll() 方法

  MyBatis 解析各种 Mapping 文件中的 SQL , 设计了一个非常关键的类 SqlNode,xml 中的每个 Node 都会解析为一个 SqlNode 对象,最后把所有的 SqlNode 拼装到一起就成了一条完整的Sql 语句


组合模式的优缺点:

  优点:
    清楚的定义分层次的复杂对象,表示对象的全部或部分层次

    让客户端忽略层次的差异,方便对整个层次结构进行控制

    简化客户端代码

    符合开闭原则


  缺点:
    限制类型时会比较复杂

    使设计变得更加抽象


作业:

  2、请用组合模式实现一个无限级扩展的树(提示,可以引入xpath)。
  id parentId xpath level
  1 1 /1 1
  2 1 /1/2 2
  3 2 /1/2/3 3









posted @ 2020-08-12 10:47  离散音符  阅读(167)  评论(0编辑  收藏  举报