22种设计模式——组合模式

1. 概述

组合模式是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。

在这里插入图片描述
这种设计模式也蛮简单的,说一种设计模式简单,怎么看的呢?看它的应用场景,应用场景很清晰就很简单,因为具体实现其实可以说是死代码,只要记住哪种场景可以使用哪种模式即可,代码实现倒是不必死记硬背,明确使用场景倒是首要的。

组合模式的使用场景很清楚,它适用于多个对象之间的关系是树状的情况(程序员应该不会不知道树的吧),这种场景其实也挺常见的,比如我们的学校架构,首先根节点是学校,然后接下来是学院,每个学院又有每个学院的专业,专业下面又有班,这就构成了一种树状关系。
在这里插入图片描述
其实有一说一,这种情况常见是常见,但我们一般不会在业务中(JavaWeb)处理这些关系,一般都是交给了数据库层(一对一、一对多)处理的。但是现在假如我们遇到了该怎么办呢?应该如何处理呢?

从上面这个学校架构的例子下手,首先最容易想到也最不实用的方法就是使用继承,即学校作为最高的父类,学院类继承学校类,专业类继承学院类,班级类继承专业类,为什么说这个方法不实用呢?

因为它使用的是继承,使用继承在逻辑上也说不过去,且无法解决一个很核心的问题:众所周知,在树中一个很核心的问题就是遍历,现在使用继承,那怎么遍历这个类构成的树呢?比如说怎么从一个学校找到它里面有什么学院?从一个学院怎么找到它有什么专业?很明显使用继承无法解决这个问题。

那该怎么做呢?其实答案也不难,使用组合,我在除了叶子节点(这个例子里面是班级类),其他节点里面都设置一个List集合来存储下一层的节点,比如学校类里面使用一个List存储学院类,学院类里面用List存储专业类。这样做可以了吗?

可以,组合模式就是使用的聚合,但是也不仅仅是这样,组合模式还加入了一个位于顶层的抽象类或者接口,这样做有什么好处呢?

好处就是可以定义所有类共有的一些方法,或者部分类共有的方法,这样客户端不必了解所有类,因为他们都实现或继承了同样的接口,在客户端眼里它们都是相同的,客户端只要了解接口或抽象类怎么使用即可,这样就达到了便于管理的目的。当然,如果某些类有自己的独特操作,客户端也是需要了解一下的。

其实如果定义了抽象类的话,可能就会产生单继承的限制,但总体使用比定义接口方便(个人感觉),因为可以写属性、空方法、抽象方法等。
在这里插入图片描述

当然抽象出一个顶层的抽象类或者接口,这个可能也是它的缺点所在,当一些类的差别比较大时,就会比较难抽象出一个抽象类或者接口,又或者抽象出来的抽象类或接口逻辑比较古怪难理解。具体还是看下面的代码实现。

  • 总结
    1. 组合模式适用于解决树状的类关系情况,使用组合,而不是继承,关联起了一个树状的类的关系图
    2. 组合模式抽象出来了一个位于顶层的抽象类或者接口,定义了所有类共有的特性,也降低客户端的使用难度。

2. 特点

  • 优点

    1. 你可以利用多态和递归机制更方便地使用复杂树结构。
    2. 开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
  • 缺点

    1. 对于功能差异较大的类, 提供公共接口或许会有困难。 在特定情况下, 你需要过度一般化组件接口, 使其变得令人难以理解。
  • 使用场景

    1. 如果你需要实现树状对象结构, 可以使用组合模式。

      组合模式为你提供了两种共享公共接口的基本元素类型: 简单叶节点和复杂容器。 容器中可以包含叶节点和其他容器。 这使得你可以构建树状嵌套递归对象结构。

    2. 如果你希望客户端代码以相同方式处理简单和复杂元素, 可以使用该模式。

      组合模式中定义的所有元素共用同一个接口。 在这一接口的帮助下, 客户端不必在意其所使用的对象的具体类。


3. 实现

  • UML类图
    在这里插入图片描述

  • 角色说明

    1. 顶层的抽象类或接口:定义了所有子类或实现类共有的功能,推荐使用抽象类,因为可以有成员变量,也可以定义所有子类都有的方法(抽象方法),也可以定义部分子类有的方法(空方法)。
    2. 非叶子类:指例子中的学校、学院,非叶子类要组合一个抽象类集合用于表示子节点
    3. 叶子类:指例子中的班级,这个位于最底层,没有子节点,无需组合一个抽象类集合
    4. 客户端:调用组合模式的角色
  • Java实现

    1. 顶层的抽象类或接口
      /**
      * @Author: chy
      * @Description: 抽象类,含有每个类都有的功能
      * @Date: Create in 20:23 2021/3/11
      */
      public abstract class Deportment {
             
         /**
          * 部门名字
          */
         
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值