责任链模式:灵活可扩展的责任传递艺术(行为模式)

在复杂的软件系统中,一个请求往往需要经过多个处理者的校验或处理。如何优雅地组织这些处理逻辑,避免复杂的条件分支和耦合?责任链模式给出了完美的解决方案。

🎯 模式意图

责任链模式是一种行为设计模式,它将请求的发送者和接收者解耦,让多个对象都有机会处理这个请求。这些对象被连接成一条链,请求沿着链传递,直到有一个对象处理它为止。

核心思想:让多个处理对象都有机会处理请求,从而避免请求发送者与接收者之间的耦合关系。

🔍 现实世界比喻

想象一下公司的审批流程:

  • 员工提交报销申请

  • 申请先到项目经理(金额 ≤ 1000元)

  • 超过权限则转交部门总监(1000元 < 金额 ≤ 5000元)

  • 再超过则转交CFO(5000元 < 金额 ≤ 10000元)

  • 最终到CEO(金额 > 10000元)

每个审批者只关心自己权限范围内的事情,不知道也不关心后续的审批者是谁。这就是责任链模式的完美体现!

💻 传统处理方式的问题

先来看看我们想要改进的"反模式":

复制代码
// ❌ 糟糕的if-else嵌套:难以维护和扩展
fun handleRequest(request: Request) {
    if (request.type == "A" && request.amount <= 1000) {
        // 项目经理处理逻辑
        println("项目经理审批通过")
    } else if (request.type == "A" && request.amount <= 5000) {
        // 部门总监处理逻辑
        println("部门总监审批通过")
    } else if (request.type == "B" && request.amount <= 2000) {
        // 特殊类型B的处理逻辑
        println("特殊类型B审批通过")
    } else if (request.amount <= 10000) {
        // CFO处理逻辑
        println("CFO审批通过")
    } else {
        // CEO处理逻辑
        println("CEO审批通过")
    }
}

问题分析:

  • 条件分支复杂,难以理解和维护

  • 违反开闭原则:新增处理逻辑需要修改原有代码

  • 处理逻辑耦合在一起,复用性差

  • 难以动态调整处理顺序

🚀 责任链模式的优雅实现

基础责任链模式

复制代码
// 请求类
data class Request(
    val type: String,
    val amount: Double,
    val content: String
)

// 处理结果
data class Response(
    val approved: Boolean,
    val message: String,
    val handler: String
)

// 抽象处理者
abstract class Handler {
    protected var nextHandler: Handler? = null
    
    fun setNext(handler: Handler): Handler {
        this.nextHandler = handler
        return handler  // 支持链式调用
    }
    
    // 模板方法:定义处理流程
    fun handle(request: Request): Response {
        return if (canHandle(request)) {
            doHandle(request)
        } else {
            nextHandler?.handle(request) 
                ?: Response(false, "无人能够处理该请求", "系统")
        }
    }
    
    // 子类实现:判断是否能处理
    protected abstract fun canHandle(request: Request): Boolean
    
    // 子类实现:具体处理逻辑
    protected abstract fun doHandle(request: Request): Response
}

具体处理者实现

复制代码
// 项目经理:处理1000元以下的请求
class ProjectManagerHandler : Handler() {
    override fun canHandle(request: Request): Boolean {
        return request.amount <= 1000
    }
    
    override fun doHandle(request: Request): Response {
        println("项目经理处理请求:${request.content},金额:${request.amount}")
        return Response(true, "项目经理审批通过", "项目经理")
    }
}

// 部门总监:处理1000-5000元的请求
class DepartmentManagerHandler : Handler() {
    override fun canHandle(request: Request): Boolean {
        return request.amount > 1000 && request.amount <= 5000
    }
    
    override fun doHandle(request: Request): Response {
        println("部门总监处理请求:${request.content},金额:${request.amount}")
        return Response(true, "部门总监审批通过", "部门总监")
    }
}

// CFO:处理5000-10000元的请求
class CFOHandler : Handler() {
    override fun canHandle(request: Request): Boolean {
        return request.amount > 5000 && request.amount <= 10000
    }
    
    override fun doHandle(request: Request): Response {
        println("CFO处理请求:${request.content},金额:${request.amount}")
        return Response(true, "CFO审批通过", "CFO")
    }
}

// CEO:处理10000元以上的请求
class CEOHandler : Handler() {
    override fun canHandle(request: Request): Boolean {
        return request.amount > 10000
    }
    
    override fun doHandle(request: Request): Response {
        println("CEO处理请求:${request.content},金额:${request.amount}")
        return Response(true, "CEO审批通过", "CEO")
    }
}

客户端使用

复制代码
// 构建责任链
fun createChain(): Handler {
    val projectManager = ProjectManagerHandler()
    val departmentManager = DepartmentManagerHandler()
    val cfo = CFOHandler()
    val ceo = CEOHandler()
    
    // 链式设置:项目经理 -> 部门总监 -> CFO -> CEO
    projectManager.setNext(departmentManager)
        .setNext(cfo)
        .setNext(ceo)
    
    return projectManager
}

// 使用责任链
fun main() {
    val handlerChain = createChain()
    
    val requests = listOf(
        Request("差旅费", 800.0, "张三出差报销"),
        Request("设备采购", 3500.0, "购买办公电脑"),
        Request("市场活动", 8500.0, "产品发布会"),
        Request("战略投资", 50000.0, "新项目投资")
    )
    
    requests.forEach { request ->
        val response = handlerChain.handle(request)
        println("结果:${response.message}\n")
    }
}

🌟 高级特性:可中断的责任链

有时候我们需要在某个处理者处中断链的传递:

复制代码
// 支持中断的责任链
abstract class StoppableHandler : Handler() {
    
    final override fun handle(request: Request): Response {
        return if (canHandle(request)) {
            doHandle(request)
        } else if (shouldContinue(request)) {
            nextHandler?.handle(request) 
                ?: Response(false, "请求未被处理", "系统")
        } else {
            Response(false, "处理流程被中断", this::class.simpleName ?: "未知处理者")
        }
    }
    
    // 子类可重写:决定是否继续传递
    protected open fun shouldContinue(request: Request): Boolean = true
}

// 特殊处理者:遇到敏感请求时中断链
class SecurityHandler : StoppableHandler() {
    override fun canHandle(request: Request): Boolean {
        return request.type == "SENSITIVE"
    }
    
    override fun doHandle(request: Request): Response {
        return Response(false, "敏感请求需要特殊审批", "安全处理器")
    }
    
    override fun shouldContinue(request: Request): Boolean {
        // 敏感请求不继续传递
        return request.type != "SENSITIVE"
    }
}

🏗️ 动态配置的责任链

责任链的强大之处在于可以动态组合:

复制代码
class DynamicHandlerChain {
    private val handlers = mutableListOf<Handler>()
    
    fun addHandler(handler: Handler): DynamicHandlerChain {
        handlers.add(handler)
        return this
    }
    
    fun build(): Handler {
        if (handlers.isEmpty()) {
            throw IllegalStateException("至少需要一个处理者")
        }
        
        // 动态构建链
        for (i in 0 until handlers.size - 1) {
            handlers[i].setNext(handlers[i + 1])
        }
        
        return handlers.first()
    }
    
    // 根据配置动态创建链
    fun buildFromConfig(config: List<String>): Handler {
        handlers.clear()
        
        config.forEach { handlerType ->
            val handler = when (handlerType) {
                "ProjectManager" -> ProjectManagerHandler()
                "DepartmentManager" -> DepartmentManagerHandler()
                "CFO" -> CFOHandler()
                "CEO" -> CEOHandler()
                "Security" -> SecurityHandler()
                else -> throw IllegalArgumentException("未知的处理者类型: $handlerType")
            }
            addHandler(handler)
        }
        
        return build()
    }
}

// 动态配置使用示例
val dynamicChain = DynamicHandlerChain()
    .buildFromConfig(listOf("ProjectManager", "Security", "DepartmentManager", "CFO"))

📊 模式结构解析

复制代码
Client → Handler ←→ ConcreteHandler1 ←→ ConcreteHandler2 ←→ ...
                     │                    │
                canHandle()          canHandle()
                doHandle()           doHandle()
  • Handler:抽象处理者,定义处理接口和链结构

  • ConcreteHandler:具体处理者,实现具体的处理逻辑

  • Client:客户端,创建责任链并提交请求

  • Request/Response:请求和响应对象

🎯 优势总结

优势 说明
解耦​ 请求发送者与接收者完全解耦
动态灵活​ 可以动态调整处理顺序和组合
单一职责​ 每个处理者只关注自己的职责范围
开闭原则​ 新增处理者无需修改现有代码
可配置性​ 处理流程可以外部配置

🔄 与其他模式的关系

  • 与组合模式:责任链常与组合模式结合,处理组合结构中的请求

  • 与命令模式:命令对象可以作为请求在责任链中传递

  • 与装饰器模式:都使用链式结构,但目的不同(装饰器增强功能,责任链传递请求)

💡 实际应用场景

Spring框架的拦截器链

复制代码
// Spring MVC的拦截器责任链
class AuthInterceptor : HandlerInterceptor {
    override fun preHandle(request: HttpServletRequest, 
                          response: HttpServletResponse, 
                          handler: Any): Boolean {
        // 认证逻辑
        return true  // 继续传递
    }
}

class LoggingInterceptor : HandlerInterceptor {
    override fun preHandle(request: HttpServletRequest,
                          response: HttpServletResponse, 
                          handler: Any): Boolean {
        // 日志记录
        return true  // 继续传递
    }
}

Android事件分发机制

复制代码
// View事件分发就是责任链的典型应用
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
    // 1. 自己处理
    if (onTouchEvent(event)) return true
    
    // 2. 子View处理
    for (i in childCount - 1 downTo 0) {
        if (dispatchTransformedTouchEvent(event, getChildAt(i))) {
            return true
        }
    }
    
    // 3. 上级处理
    return super.dispatchTouchEvent(event)
}

Servlet Filter过滤器链

复制代码
// Java Web中的过滤器责任链
public class LoggingFilter implements Filter {
    public void doFilter(ServletRequest request, 
                        ServletResponse response, 
                        FilterChain chain) {
        // 前置处理
        logRequest(request);
        
        // 传递到下一个过滤器
        chain.doFilter(request, response);
        
        // 后置处理
        logResponse(response);
    }
}

🚀 最佳实践建议

  1. 控制链的长度:避免过长的责任链影响性能

  2. 设置终止条件:确保请求最终能被处理或明确拒绝

  3. 记录处理轨迹:对于调试,可以记录请求经过的处理者

  4. 考虑性能优化:对于高频请求,可以缓存链的配置

  5. 异常处理:统一处理链中的异常,避免链中断

变体与扩展

功能链 vs 决策链

  • 功能链:每个处理者都执行一些操作(如过滤器链)

  • 决策链:只有一个处理者真正处理请求(如审批链)

双向责任链

复制代码
abstract class BidirectionalHandler {
    protected var next: BidirectionalHandler? = null
    protected var prev: BidirectionalHandler? = null
    
    fun handle(request: Request): Response {
        // 正向处理
        val response = doHandle(request)
        
        // 如果需要反向传递结果
        if (needReversePropagation(response)) {
            return reversePropagate(response)
        }
        
        return response
    }
}

总结

责任链模式通过解耦请求发送者与接收者,提供了一种灵活处理请求的机制。它让软件系统更加:

✅ 灵活可扩展:动态调整处理流程

✅ 职责清晰:每个处理者专注单一职责

✅ 维护性好:符合开闭原则,易于扩展

✅ 复用性强:处理者可以在不同链中复用

当你遇到需要经过多个处理步骤的请求,或者处理流程需要动态配置的场景时,责任链模式是你的不二选择!

相关推荐
阿砾17 小时前
微信群消息处理:回调乱序、自己发的消息、群内真实发送者
微信
承渊政道18 小时前
飞牛NAS部署Hermes AI Agent:接入DeepSeek、微信与公网访问完整教程
人工智能·微信·nas·deepseek·hermes
高晶2 天前
微信小程序实战:iOS 降级查询工具从零开发
微信·程序员
软擎2 天前
花店节日布置怎么留记录?用轻虾导出助手把花材替换、现场尺寸与撤场清点钉在一起
微信
jaysee-sjc3 天前
【苍穹外卖】Day12:工作台数据看板与 Excel 报表导出
java·开发语言·数据库·spring boot·spring·微信·excel
极客互动API4 天前
【极客互动】企业微信外部群聊机器人开发实战与效果验证
微信·机器人·企业微信·企微scrm·企业微信api·企微外部联系人
特视界说5 天前
多规格产品动画怎么规划?把“一个型号一条片”改成可管理的内容架构
人工智能·安全·微信·新浪微博
悟空码字5 天前
视频号直播变了
微信·视频号
随性而行3607 天前
企业微信 Webhook 接收不到消息?网络连通性、URL 签名验签与 API 返回错误码排查指南
java·网络·人工智能·后端·微信·企业微信
未秃头的程序猿8 天前
同一个商户号,V2 免密代扣和 V3 分账的证书怎么共存?
java·后端·微信