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

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

🎯 模式意图

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

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

🔍 现实世界比喻

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

  • 员工提交报销申请

  • 申请先到项目经理(金额 ≤ 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
    }
}

总结

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

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

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

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

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

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

相关推荐
Jomurphys2 小时前
设计模式 - 责任链模式 Chain of Responsibility Pattern
android·设计模式·责任链模式
孙严Pay2 小时前
快捷支付和网关支付到底哪个更安全呢?
笔记·科技·计算机网络·其他·微信
陈思杰系统思考Jason1 天前
业务创新与系统思考
百度·微信·微信公众平台·新浪微博·微信开放平台
liugang_lawyer2 天前
防范新型金融诈骗
笔记·百度·微信·金融·微信公众平台·新浪微博
陈思杰系统思考Jason3 天前
系统思考:决策
百度·微信·微信公众平台·新浪微博·微信开放平台
优梦创客3 天前
3 天搞定微小游戏上架!独立开发者副业赚钱全攻略(附选题 / 技术 / 运营干货)
微信·教程·小游戏·游戏开发
Jing_Rainbow3 天前
【 Weapp-3 /Lesson20(2025-11-04)】路虎卫士小程序开发详解:从架构到细节的深度解析🚙📱
微信·微信小程序·程序员
Jing_Rainbow4 天前
【Weapp-2 /Lesson19(2025-11-04)】微信小程序“博客园”项目深度解析:从架构到细节的完整剖析📱
微信·微信小程序·程序员