在复杂的软件系统中,一个请求往往需要经过多个处理者的校验或处理。如何优雅地组织这些处理逻辑,避免复杂的条件分支和耦合?责任链模式给出了完美的解决方案。
🎯 模式意图
责任链模式是一种行为设计模式,它将请求的发送者和接收者解耦,让多个对象都有机会处理这个请求。这些对象被连接成一条链,请求沿着链传递,直到有一个对象处理它为止。
核心思想:让多个处理对象都有机会处理请求,从而避免请求发送者与接收者之间的耦合关系。
🔍 现实世界比喻
想象一下公司的审批流程:
-
员工提交报销申请
-
申请先到项目经理(金额 ≤ 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);
}
}
🚀 最佳实践建议
-
控制链的长度:避免过长的责任链影响性能
-
设置终止条件:确保请求最终能被处理或明确拒绝
-
记录处理轨迹:对于调试,可以记录请求经过的处理者
-
考虑性能优化:对于高频请求,可以缓存链的配置
-
异常处理:统一处理链中的异常,避免链中断
变体与扩展
功能链 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
}
}
总结
责任链模式通过解耦请求发送者与接收者,提供了一种灵活处理请求的机制。它让软件系统更加:
✅ 灵活可扩展:动态调整处理流程
✅ 职责清晰:每个处理者专注单一职责
✅ 维护性好:符合开闭原则,易于扩展
✅ 复用性强:处理者可以在不同链中复用
当你遇到需要经过多个处理步骤的请求,或者处理流程需要动态配置的场景时,责任链模式是你的不二选择!