1. 概述

设计模式是解决代码组织问题的重要手段之一,其核心目标之一就是实现松耦合(loose coupling)。责任链(Chain of Responsibility)模式正是为此而生的经典行为型设计模式。

本文将通过一个实际的 Kotlin 示例,深入剖析责任链模式的设计思想与实现方式,帮助你在实际项目中更好地应用这一模式,避免“请求处理逻辑层层嵌套”的踩坑场景。

2. 什么是责任链设计模式?

责任链模式的核心思想是:将请求的发送者与处理者解耦,让多个对象都有机会处理该请求,形成一条处理链条

✅ 客户端只需把请求发给链头,无需关心具体由谁处理
✅ 每个处理节点自行决定是否处理该请求,若无法处理则转发给下一个节点
✅ 链条的结构可以在运行时动态构建,灵活扩展

举个现实中的例子:用户拨打客服热线反馈问题。
首先由技术支持接听,若无法解决,则转交计费部门;若仍无法解决,再转至客户满意度团队。整个流程就像一条“问题传递链”,直到某个环节能处理为止。

⚠️ 如果整条链都无法处理,请求最终会被拒绝或返回默认响应。

这种模式的优势在于:

  • ✅ 新增处理类型无需修改现有代码,符合开闭原则
  • ✅ 请求处理逻辑集中管理,避免 if-elseswitch-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 下来结合调试运行,加深理解。


原始标题:The Chain of Responsibility Pattern in Kotlin