1. 概述
设计模式是解决代码组织问题的重要手段之一,其核心目标之一就是实现松耦合(loose coupling)。责任链(Chain of Responsibility)模式正是为此而生的经典行为型设计模式。
本文将通过一个实际的 Kotlin 示例,深入剖析责任链模式的设计思想与实现方式,帮助你在实际项目中更好地应用这一模式,避免“请求处理逻辑层层嵌套”的踩坑场景。
2. 什么是责任链设计模式?
责任链模式的核心思想是:将请求的发送者与处理者解耦,让多个对象都有机会处理该请求,形成一条处理链条。
✅ 客户端只需把请求发给链头,无需关心具体由谁处理
✅ 每个处理节点自行决定是否处理该请求,若无法处理则转发给下一个节点
✅ 链条的结构可以在运行时动态构建,灵活扩展
举个现实中的例子:用户拨打客服热线反馈问题。
首先由技术支持接听,若无法解决,则转交计费部门;若仍无法解决,再转至客户满意度团队。整个流程就像一条“问题传递链”,直到某个环节能处理为止。
⚠️ 如果整条链都无法处理,请求最终会被拒绝或返回默认响应。
这种模式的优势在于:
- ✅ 新增处理类型无需修改现有代码,符合开闭原则
- ✅ 请求处理逻辑集中管理,避免
if-else
或switch-case
的硬编码分支 - ✅ 易于调试和追踪请求流转路径
3. 实战演示
接下来我们用 Kotlin 实现上述客服系统,展示责任链模式的具体落地方式。
3.1 参与角色
系统包含以下关键角色:
- SupportCenterClient:客户端,发起请求
- AbstractSupportCenterHandler:抽象处理器,定义通用行为
- TechnicalSupportCenter:技术问题处理器
- BillsSupportCenter:计费问题处理器
- CustomerSatisfactionSupportCenter:客户满意度问题处理器
我们先定义一个抽象基类,作为所有处理器的公共父类:
abstract class AbstractSupportCenterHandler(private val requestType: RequestType) {
enum class RequestType {
TECHNICAL, BILL, CUSTOMER_SATISFACTION, UNKNOWN
}
open var nextHandler: AbstractSupportCenterHandler? = null
open fun nextHandler(handler: AbstractSupportCenterHandler) {
this.nextHandler = handler
}
open fun receiveRequest(requestType: RequestType, message: String): String {
when (this.requestType == requestType) {
true -> return handleRequest(message)
else -> return nextHandler?.receiveRequest(requestType, message)
?: return "No next handler for this request"
}
}
protected abstract fun handleRequest(message: String): String
}
📌 关键点说明:
nextHandler
:指向链中的下一个处理器,构成链式结构receiveRequest()
:核心入口方法,判断当前处理器是否匹配请求类型handleRequest()
:抽象方法,由子类实现具体处理逻辑
3.2 处理器实现
每个具体处理器继承 AbstractSupportCenterHandler
,并指定自己的处理类型和下一跳。
技术支持中心
class TechnicalSupportCenter(requestType: RequestType) : AbstractSupportCenterHandler(requestType) {
override var nextHandler: AbstractSupportCenterHandler? =
BillsSupportCenter(RequestType.BILL)
override fun handleRequest(message: String): String {
return "Handler: TechnicalSupportHandler - request: $message"
}
}
计费支持中心
class BillsSupportCenter(requestType: RequestType) : AbstractSupportCenterHandler(requestType){
override var nextHandler: AbstractSupportCenterHandler =
CustomerSatisfactionSupportCenter(RequestType.CUSTOMER_SATISFACTION)
override fun handleRequest(message: String): String {
return "Handler: BillsSupportHandler - request: $message"
}
}
客户满意度中心
class CustomerSatisfactionSupportCenter(
requestType: RequestType
) : AbstractSupportCenterHandler(requestType) {
override var nextHandler: AbstractSupportCenterHandler? = null
override fun handleRequest(message: String): String {
return "Handler: CustomerSatisfactionSupportHandler - request: $message"
}
}
📌 注意:
- 每个处理器在构造时就指定了
nextHandler
,形成静态链 - 实际项目中可通过配置或依赖注入动态组装链条,更灵活
客户端初始化
object SupportCenterClient {
val technicalHandler =
TechnicalSupportCenter(AbstractSupportCenterHandler.RequestType.TECHNICAL)
}
客户端从链头(技术支持)开始发起请求,自动触发后续流转。
4. 测试验证
我们通过几个测试用例验证责任链的正确性。
✅ 场景一:技术问题由技术支持处理
@Test
fun `support center attempt to process technical request`(){
val result1 = SupportCenterClient.technicalHandler
.receiveRequest(AbstractSupportCenterHandler.RequestType.TECHNICAL, "technical issue.")
assertEquals("Handler: TechnicalSupportHandler - request: technical issue.", result1)
}
👉 请求被链头直接处理,未向下传递。
✅ 场景二:计费问题由计费部门处理
@Test
fun `support center attempt to process billing request`(){
val result = SupportCenterClient.technicalHandler
.receiveRequest(AbstractSupportCenterHandler.RequestType.BILL, "billing issue.")
assertEquals("Handler: BillsSupportHandler - request: billing issue.", result)
}
👉 技术支持无法处理,自动转发给 BillsSupportCenter
。
✅ 场景三:客户满意度问题由专属团队处理
@Test
fun `support center attempt to process customer happiness request`(){
val result = SupportCenterClient.technicalHandler
.receiveRequest(
AbstractSupportCenterHandler.RequestType.CUSTOMER_SATISFACTION,
"customer satisfaction issue."
)
assertEquals(
"Handler: CustomerSatisfactionSupportHandler - request: customer satisfaction issue.",
result
)
}
👉 请求经过两次转发,最终由链尾处理。
❌ 场景四:未知请求无法被任何处理器处理
@Test
fun `no center can process client request`(){
val result = SupportCenterClient.technicalHandler
.receiveRequest(AbstractSupportCenterHandler.RequestType.UNKNOWN, "Other issue.")
assertEquals("No next handler for this request", result)
}
👉 所有处理器均不匹配,且无后续节点,返回默认提示。
5. 总结
责任链模式适用于多级条件判断、请求需按顺序尝试处理的场景,例如:
- 审批流(请假、报销)
- 异常处理链
- 过滤器链(如 Spring Interceptor)
- 权限校验层级
📌 使用建议:
- ✅ 优先使用组合而非继承构建链条,提升灵活性
- ✅ 考虑加入超时或最大跳数限制,防止无限循环
- ✅ 日志记录请求流转过程,便于排查问题
示例代码已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-design-patterns
建议 clone 下来结合调试运行,加深理解。