1、问题背景

对在消息进行处理的过程中,发现有这样的需求,存在一种组合处理器,由各子处理进行组合,来提供处理器的功能,单一处理器与组件处理器,拥有相同的对外功能。

2、组合模式

2.1 组合模式的定义与特点

组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。

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

由上图可以看出,其实根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。

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

组合模式的主要优点有:

  1. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
  2. 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

其主要缺点是:

  1. 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  2. 不容易限制容器中的构件;
  3. 不容易用继承的方法来增加构件的新功能;

2.2 组合模式的结构与实现

1. 模式的结构

组合模式包含以下主要角色。

  1. 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
  2. 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
  3. 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

组合模式分为透明式的组合模式和安全式的组合模式。

(1) 透明方式

在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。其结构图如图 1 所示。

(2) 安全方式

在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。其结构图如图 2 所示。

3、核心源代码

3.1 单一处理器 RedisDelayQueueHandler源码

package cn.vetech.center.cps.flsc.service.common.delayqueue;import org.springframework.plugin.core.Plugin;/*** 基于redis的延迟队列的消息处理器接口* @author LiQiao* @date 2022/03/04*/
public interface RedisDelayQueueHandler extends Plugin<RedisDelayMsgTypeEnum> {public static final String NAME = "redisDelayQueueHandlerRegistry";/*** 延迟消息的消费业务逻辑* * @author LiQiao* @date 2022年3月4日 上午11:06:01* @param redisDelayQueueItem*/void execute(RedisDelayQueueItem redisDelayQueueItem);}

3.2 组合处理器CompositeHandler源码

package cn.vetech.center.cps.flsc.service.common.delayqueue.handler;import java.util.ArrayList;
import java.util.List;import org.vetech.core.modules.utils.collection.ListUtil;import cn.vetech.center.cps.flsc.common.constant.MagicNumberConst;
import cn.vetech.center.cps.flsc.service.common.delayqueue.RedisDelayMsgTypeEnum;
import cn.vetech.center.cps.flsc.service.common.delayqueue.RedisDelayQueueHandler;
import cn.vetech.center.cps.flsc.service.common.delayqueue.RedisDelayQueueItem;
import lombok.Data;/*** 组合处理器,可以处理多个redis延迟消息类型* @author LiQiao* @date 2022/03/10*/@Data
public abstract class CompositeHandler implements RedisDelayQueueHandler {private List<RedisDelayQueueHandler> redisDelayQueueHandlerList;protected void add(RedisDelayQueueHandler redisDelayQueueHandler) {if (ListUtil.isEmpty(redisDelayQueueHandlerList)) {this.redisDelayQueueHandlerList = new ArrayList<>(MagicNumberConst.INT10);}this.redisDelayQueueHandlerList.add(redisDelayQueueHandler);}@Overridepublic final void execute(RedisDelayQueueItem redisDelayQueueItem) {if (ListUtil.isEmpty(this.redisDelayQueueHandlerList)) {return;}for (RedisDelayQueueHandler redisDelayQueueHandler : this.redisDelayQueueHandlerList) {if (redisDelayQueueHandler.supports(redisDelayQueueItem.getRedisDelayMsgTypeEnum())) {redisDelayQueueHandler.execute(redisDelayQueueItem);}}}@Overridepublic final boolean supports(RedisDelayMsgTypeEnum redisDelayMsgTypeEnum) {if (ListUtil.isEmpty(this.redisDelayQueueHandlerList)) {return false;}for (RedisDelayQueueHandler redisDelayQueueHandler : this.redisDelayQueueHandlerList) {if (redisDelayQueueHandler.supports(redisDelayMsgTypeEnum)) {return true;}}return false;}}

4、总结

这是对组合模式一个应用场景,对于设计模式,我们平时,需要对理论与实践加以结合,才能
适当的运用这些设计模式帮助我们解决重复的设计问题。

利用组合模式来实现组件处理器的工程实践相关推荐

  1. 《研磨设计模式》chap25 访问者模式Visitor(3)联合组合模式+总结

    1. 联合组合模式 //抽象的组件对象,相当于访问者模式中的元素对象 public abstract class Component {//接受访问者的访问 public abstract void ...

  2. 实现树状结构_组合模式 - 树状结构的优雅实现

    在编程实践中,经常会遇到树状结构的场景,比如我们的浏览器窗口,比如文件系统. 那么,在处理树状结构的时候有什么较好的方式呢? 现在,我们就来学习一种利用组合模式的方法. 如上图所示,我们通过程序输出的 ...

  3. C#设计模式——组合模式(Composite Pattern)

    一.概述 在软件开发中,我们往往会遇上类似树形结构的对象体系.即某一对象既可能在树形结构中作为叶节点存在,也可能作为分支节点存在.比如在文件系统中,文件是作为叶节点存在,而文件夹就是分支节点.在设计这 ...

  4. 《Head First 设计模式》读书笔记——组合模式

    承接上篇博客,我们需要修改所有的菜单,以满足可以添加子菜单,但是我们由于已经把整个项目的框架搭好了,不可能重新实现菜单,所以我们只能修改,那么我们需要做些什么呢? 树形结构,可以容纳菜单.子菜单和菜单 ...

  5. 设计模式——(12)组合模式

    第十二章 组合模式 1.1 引言 餐厅都有自己的一份菜单,而菜单由菜单项组成,每个菜单项描述菜名.菜价和描述等信息. 而在一份菜单中,可能包含子菜单,例如:餐厅菜单除了包含菜名,还包含一份甜品子菜单. ...

  6. 《HeadFirst设计模式》第九章-2组合模式

    1.声明 设计模式中的设计思想.图片和部分代码参考自<Head First设计模式>,作者Eric Freeman & Elisabeth Freeman & Kathy ...

  7. 设计模式之组合模式(Composite)

    1.引言 在学习JUnit的时候,看到一段话"JUnit框架是一个典型的Composite模式:TestSuite可以容纳任何派生自Test的对象:当调用TestSuite对象的run()方 ...

  8. 梳理公司的组织架构 --- 组合模式

    题外话 本来是周更的频率, 因为真实的"小光"真实地逃离了北京, 回了武汉, 回了老家, 处理了一些私人事务. 也就有快一个月时间没有更新了, 抱歉. 年终总结也都没有时间写, 抽 ...

  9. React组件设计模式与最佳实践

    React设计思想 UI=f(data)XUI = f(data)XUI=f(data)X 在React中,界面完全由数据驱动 在React中,一切都是组件 用户界面就是组件 export defau ...

最新文章

  1. C++ ——统一初始化
  2. jenkins和docker实现自动化构建部署
  3. Install FileZilla in Ubuntu16.04
  4. Google研究员Ilya Sutskever:成功训练LDNN的13点建议
  5. java 与c 运行效率_Java语言与C语言代码运行效率的比较
  6. MGraph图(代码、分析、汇编)
  7. linux-文件类型-七种
  8. 马云获福布斯终身成就奖;华为推出首款 4G 芯片 Balong 711;PyPy 7.2 发布 | 极客头条...
  9. spring学习--引入外部文件,初始化属性
  10. 空间参考---墨卡托投影、高斯-克吕格投影、UTM投影的异同
  11. 64qam带宽计算_64QAM有效传输速率计算
  12. Trustzone OP-TEE 在QEMU平台上的编译、运行与测试
  13. 好的医疗器械管理软件应该具备哪些功能?
  14. 怎么用计算机算国际象棋,一台会判断的计算机:自学72小时就能成国际象棋大师...
  15. 华为路由器显示网络未连接到服务器,如何解决华为路由器Q1连接没有网络的问题?...
  16. 学计算机的是不是都非常木讷,北大学神韦东奕​是正常人吗?内向木讷是缺点​,拿不出手?​...
  17. LVDT/RVDT(线性/旋转可变差动变压器)、Resolver(旋转变压器)仿真方案
  18. 数据库的schemas(模式)
  19. javaAPI文档中文版(JDK11在线版)无需下载、直接打开
  20. 高效理解pytorch的backward需要scalar outputs

热门文章

  1. 约翰·卡马克(John Carmack的全名是John D. Carmack II)
  2. 【高德地图进阶】--- 3d城市版块之wall
  3. C++大学教程(第二版)c++how to program Second Edition --电子工业出版社【美】harvey M.Deitel and paul James Deitel(更新中)
  4. JS EventListener
  5. 手动安装Python库或安装第三方库的方法
  6. soul_dubbo
  7. 拉格朗日对偶函数拉格朗日对偶问题
  8. Nginx日志格式配置-转载
  9. 浅谈互联网DD攻击和CC攻击
  10. 逻辑代数几个重要定理