责任链抽象模板设计分析 (基于 Git Diff 2.9 - 2.10)¶
本文档基于提供的 git diff 文件,分析其中实现的责任链模式的两种模型,并阐述其相关知识。
责任链模式 (Chain of Responsibility Pattern)¶
作用与意图¶
责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下一个处理者。
核心思想¶
- 解耦请求发送者和接收者:发送者不需要知道哪个对象会处理其请求,链中的对象也不需要知道发送者的细节。
- 动态组合责任:可以在运行时动态地组合链中的处理者,或者修改它们的顺序。
- 请求逐级处理:请求在链上传递,直到有一个处理者处理它为止。
模型设计¶
- 如图,这是一种多实例对象责任链的设计结构,会使用到如 Java JDK 源码中 Link 的方式填写链路,之后再有业务链路处理链路执行。而每一个链路都会被填充一个逻辑处理器的实现类(ILogicHandler)来处理具体的业务。
- 那么,这样就很好的扩展了各种链路的使用诉求。
适用场景¶
- 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时。
- 当必须按顺序执行多个处理器时。
- 当所需处理器集合及其顺序仅在运行时可用时。
代码实现分析¶
Git diff 中展示了两种责任链(或类似链路处理)的实现模型,分别位于 model1
和 model2
相关的代码中。
Model 1: 单例责任链 (Singleton Chain of Responsibility)¶
这种模型更接近传统的责任链定义,通过显式链接构建处理者链条。
核心接口与抽象类¶
ILogicLink<T, D, R>
: 定义链中单个节点的行为接口。它继承自ILogicChainArmory
,并增加了apply
方法用于处理请求。- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model1/ILogicLink.java
ILogicChainArmory<T, D, R>
: 定义链的装配能力,主要包含next()
和appendNext(ILogicLink<T, D, R> next)
方法。- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model1/ILogicChainArmory.java
AbstractLogicLink<T, D, R>
:ILogicLink
的抽象实现。它管理对下一个节点的引用 (private ILogicLink<T, D, R> next;
),并提供了将请求传递给下一个节点的protected R next(T requestParameter, D dynamicContext)
方法。- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model1/AbstractLogicLink.java
构建链¶
通过 appendNext
方法将各个逻辑节点(实现了 ILogicLink
的类,如 RuleLogic101
, RuleLogic102
)手动连接起来形成责任链。
Java | |
---|---|
请求处理流程¶
- 请求从链的头节点(如
ruleLogic101
)开始。 - 当前节点的
apply
方法被调用。节点可以处理请求,或者通过调用其父类AbstractLogicLink
的next(requestParameter, dynamicContext)
方法将请求传递给链中的下一个节点。 - 如果
next()
方法被调用,它会调用下一个链接节点的apply
方法。 - 这个过程持续进行,直到请求被某个节点完全处理(可能不再调用
next()
并返回结果),或者到达链的末尾。
相关文件¶
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model1/ILogicLink.java
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model1/ILogicChainArmory.java
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model1/AbstractLogicLink.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule01/factory/Rule01TradeRuleFactory.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule01/logic/RuleLogic101.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule01/logic/RuleLogic102.java
Model 2: 业务链路/多实例处理器链 (Business Link / Multi-instance Handler Chain)¶
这种模型使用一个集合(自定义链表)来管理一系列独立的处理器。链的执行由该集合控制,依次调用每个处理器的处理方法。
核心接口与类¶
ILogicHandler<T, D, R>
: 定义链中处理单元的接口。核心方法是apply(T requestParameter, D dynamicContext)
。- (此接口定义未在 diff 中直接显示,但其使用贯穿 Model 2 的实现)
LinkedList<E>
和ILink<E>
: 通用的双向链表数据结构及其接口,用于存储ILogicHandler
实例。- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/chain/LinkedList.java
- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/chain/ILink.java
BusinessLinkedList<T, D, R>
: 继承自LinkedList<ILogicHandler<T, D, R>>
,并且自身也实现了ILogicHandler<T, D, R>
接口。它代表一个可执行的业务链路,内部按顺序存储和执行一系列ILogicHandler
。- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/chain/BusinessLinkedList.java
LinkArmory<T, D, R>
: 一个工厂或装配类,用于方便地创建和初始化BusinessLinkedList
,将多个ILogicHandler
实例添加到链中。- 文件路径:
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/LinkArmory.java
构建链¶
LinkArmory
在其构造函数中接收一个或多个 ILogicHandler
实例,并将它们添加到内部创建的 BusinessLinkedList
中。
请求处理流程¶
- 当
BusinessLinkedList
的apply
方法被调用时,它会遍历其内部存储的ILogicHandler
节点(从first
节点开始)。 - 对于链表中的每个
ILogicHandler
(item),调用其apply
方法。 - 如果某个
item.apply(...)
返回了一个非null
的结果,BusinessLinkedList
会立即返回这个结果,后续的处理器将不再执行。 - 如果遍历完所有处理器,都没有返回非
null
的结果,则BusinessLinkedList
的apply
方法返回null
。
- 关于
ILogicHandler
内部的next()
调用: 在RuleLogic201.java
中,其apply
方法调用了next(requestParameter, dynamicContext)
。如果ILogicHandler
接口本身没有定义next
方法(或默认实现),这可能是一个未完成的特性或特定于RuleLogic201
的内部逻辑。BusinessLinkedList
的主要迭代机制是通过遍历其节点列表,而不是依赖处理器内部的next()
调用来驱动到 列表中的下一个处理器。
相关文件¶
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/handler/ILogicHandler.java
(推断)doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/LinkArmory.java
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/chain/BusinessLinkedList.java
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/chain/ILink.java
doppler-group-buy-market-types/src/main/java/site/dopplerxd/types/designs/framework/link/model2/chain/LinkedList.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule02/factory/Rule02TradeRuleFactory.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule02/logic/RuleLogic201.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule02/logic/RuleLogic202.java
doppler-group-buy-market-app/src/test/java/site/dopplerxd/test/types/rule02/logic/XxxResponse.java
总结与对比¶
- Model 1 (单例责任链):
- 结构:处理者之间通过
next
指针显式链接,形成单向链。 - 控制流:由当前处理者决定是否处理以及是否传递给下一个处理者。
-
灵活性:链的构建相对固定,但可以在抽象类中加入更多通用逻辑。
-
Model 2 (业务链路/多实例处理器链):
- 结构:处理者作为独立对象存在,由一个外部容器(
BusinessLinkedList
)按顺序管理。 - 控制流:由容器(
BusinessLinkedList
)迭代调用每个处理者的apply
方法。一旦某个处理器返回有效结果,链式调用通常会中止。 - 灵活性:更容易动态增删处理器(通过修改
BusinessLinkedList
的内容)。处理器之间耦合度更低,它们不需要知道彼此的存在,只需实现ILogicHandler
接口。
两种模型都旨在将一系列处理步骤解耦并有序地组织起来。Model 1 是经典的责任链实现,而 Model 2 更像是一个基于列表的处理器调度或组合模式,提供了另一种构建有序处理流程的思路,尤其适用于处理器返回结果即表示处理完成的场景。