责任链模式详解
什么是责任链模式?
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许将请求沿着处理者链进行传递,直到有一个处理者处理该请求为止。每个处理者都包含对下一个处理者的引用,形成一条链。
核心概念
- Handler(处理者):定义处理请求的接口,包含处理请求的方法和设置下一个处理者的方法。
- ConcreteHandler(具体处理者):实现处理者接口,处理它所负责的请求,如果不能处理则将请求传递给下一个处理者。
- Client(客户端):创建处理者链并向链头的处理者提交请求。
责任链模式的UML图
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| +----------------+ +----------------+ | Handler |<------| Handler | +----------------+ +----------------+ | -successor | | +handleRequest()| | +setSuccessor()| | +setSuccessor()| | +handleRequest()| +----------------+ +----------------+ ^ ^ | | | +----------------+ +----------------+ | ConcreteHandlerA| | ConcreteHandlerB| +----------------+ +----------------+ | +handleRequest()| | +handleRequest()| +----------------+ +----------------+
|
责任链模式的优缺点
优点
- 解耦:将请求的发送者和接收者解耦,发送者不需要知道谁处理了请求。
- 灵活性:可以动态调整处理者链的结构,添加或删除处理者。
- 单一职责:每个处理者只负责自己的处理逻辑,符合单一职责原则。
- 可扩展性:可以轻松添加新的处理者,而不需要修改现有代码。
缺点
- 效率问题:如果链过长,可能会影响请求的处理效率。
- 不确定性:请求可能会在链中传递而不被任何处理者处理。
- 调试困难:由于请求的处理路径不确定,可能会增加调试的难度。
责任链模式的实现
C++ 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| #include <iostream> #include <string>
class Handler { protected: Handler* successor; public: Handler() : successor(nullptr) {} virtual ~Handler() {} void setSuccessor(Handler* next) { successor = next; } virtual void handleRequest(int request) = 0; };
class ConcreteHandlerA : public Handler { public: void handleRequest(int request) override { if (request >= 1 && request <= 10) { std::cout << "ConcreteHandlerA handled request " << request << std::endl; } else if (successor != nullptr) { successor->handleRequest(request); } else { std::cout << "No handler can handle request " << request << std::endl; } } };
class ConcreteHandlerB : public Handler { public: void handleRequest(int request) override { if (request >= 11 && request <= 20) { std::cout << "ConcreteHandlerB handled request " << request << std::endl; } else if (successor != nullptr) { successor->handleRequest(request); } else { std::cout << "No handler can handle request " << request << std::endl; } } };
class ConcreteHandlerC : public Handler { public: void handleRequest(int request) override { if (request >= 21 && request <= 30) { std::cout << "ConcreteHandlerC handled request " << request << std::endl; } else if (successor != nullptr) { successor->handleRequest(request); } else { std::cout << "No handler can handle request " << request << std::endl; } } };
int main() { Handler* handlerA = new ConcreteHandlerA(); Handler* handlerB = new ConcreteHandlerB(); Handler* handlerC = new ConcreteHandlerC(); handlerA->setSuccessor(handlerB); handlerB->setSuccessor(handlerC); int requests[] = {5, 15, 25, 35}; for (int request : requests) { std::cout << "\nSending request " << request << std::endl; handlerA->handleRequest(request); } delete handlerA; delete handlerB; delete handlerC; return 0; }
|
Java 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| interface Handler { void setSuccessor(Handler successor); void handleRequest(int request); }
class ConcreteHandlerA implements Handler { private Handler successor; @Override public void setSuccessor(Handler successor) { this.successor = successor; } @Override public void handleRequest(int request) { if (request >= 1 && request <= 10) { System.out.println("ConcreteHandlerA handled request " + request); } else if (successor != null) { successor.handleRequest(request); } else { System.out.println("No handler can handle request " + request); } } }
class ConcreteHandlerB implements Handler { private Handler successor; @Override public void setSuccessor(Handler successor) { this.successor = successor; } @Override public void handleRequest(int request) { if (request >= 11 && request <= 20) { System.out.println("ConcreteHandlerB handled request " + request); } else if (successor != null) { successor.handleRequest(request); } else { System.out.println("No handler can handle request " + request); } } }
class ConcreteHandlerC implements Handler { private Handler successor; @Override public void setSuccessor(Handler successor) { this.successor = successor; } @Override public void handleRequest(int request) { if (request >= 21 && request <= 30) { System.out.println("ConcreteHandlerC handled request " + request); } else if (successor != null) { successor.handleRequest(request); } else { System.out.println("No handler can handle request " + request); } } }
public class ChainOfResponsibilityDemo { public static void main(String[] args) { Handler handlerA = new ConcreteHandlerA(); Handler handlerB = new ConcreteHandlerB(); Handler handlerC = new ConcreteHandlerC(); handlerA.setSuccessor(handlerB); handlerB.setSuccessor(handlerC); int[] requests = {5, 15, 25, 35}; for (int request : requests) { System.out.println("\nSending request " + request); handlerA.handleRequest(request); } } }
|
Python 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| class Handler: def __init__(self): self.successor = None def set_successor(self, successor): """设置下一个处理者""" self.successor = successor def handle_request(self, request): """处理请求""" pass
class ConcreteHandlerA(Handler): def handle_request(self, request): if 1 <= request <= 10: print(f"ConcreteHandlerA handled request {request}") elif self.successor: self.successor.handle_request(request) else: print(f"No handler can handle request {request}")
class ConcreteHandlerB(Handler): def handle_request(self, request): if 11 <= request <= 20: print(f"ConcreteHandlerB handled request {request}") elif self.successor: self.successor.handle_request(request) else: print(f"No handler can handle request {request}")
class ConcreteHandlerC(Handler): def handle_request(self, request): if 21 <= request <= 30: print(f"ConcreteHandlerC handled request {request}") elif self.successor: self.successor.handle_request(request) else: print(f"No handler can handle request {request}")
if __name__ == "__main__": handler_a = ConcreteHandlerA() handler_b = ConcreteHandlerB() handler_c = ConcreteHandlerC() handler_a.set_successor(handler_b) handler_b.set_successor(handler_c) requests = [5, 15, 25, 35] for request in requests: print(f"\nSending request {request}") handler_a.handle_request(request)
|
C# 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| using System;
interface IHandler { void SetSuccessor(IHandler successor); void HandleRequest(int request); }
class ConcreteHandlerA : IHandler { private IHandler successor; public void SetSuccessor(IHandler successor) { this.successor = successor; } public void HandleRequest(int request) { if (request >= 1 && request <= 10) { Console.WriteLine($"ConcreteHandlerA handled request {request}"); } else if (successor != null) { successor.HandleRequest(request); } else { Console.WriteLine($"No handler can handle request {request}"); } } }
class ConcreteHandlerB : IHandler { private IHandler successor; public void SetSuccessor(IHandler successor) { this.successor = successor; } public void HandleRequest(int request) { if (request >= 11 && request <= 20) { Console.WriteLine($"ConcreteHandlerB handled request {request}"); } else if (successor != null) { successor.HandleRequest(request); } else { Console.WriteLine($"No handler can handle request {request}"); } } }
class ConcreteHandlerC : IHandler { private IHandler successor; public void SetSuccessor(IHandler successor) { this.successor = successor; } public void HandleRequest(int request) { if (request >= 21 && request <= 30) { Console.WriteLine($"ConcreteHandlerC handled request {request}"); } else if (successor != null) { successor.HandleRequest(request); } else { Console.WriteLine($"No handler can handle request {request}"); } } }
class Program { static void Main(string[] args) { IHandler handlerA = new ConcreteHandlerA(); IHandler handlerB = new ConcreteHandlerB(); IHandler handlerC = new ConcreteHandlerC(); handlerA.SetSuccessor(handlerB); handlerB.SetSuccessor(handlerC); int[] requests = { 5, 15, 25, 35 }; foreach (int request in requests) { Console.WriteLine($"\nSending request {request}"); handlerA.HandleRequest(request); } } }
|
责任链模式的使用场景
1. 事件处理系统
- GUI 应用:按钮点击、键盘输入等事件的处理
- 前端框架:DOM 事件冒泡机制
- 游戏开发:游戏事件的处理
2. 审批流程
- 请假审批:从组长到经理到总监的审批流程
- 报销审批:不同金额的报销需要不同级别的审批
- 采购审批:不同金额的采购需要不同级别的审批
3. 过滤器/拦截器
- Web 框架:请求拦截器、过滤器链
- 安全系统:权限验证、身份认证、防 CSRF 攻击等
- 日志系统:不同级别的日志处理
4. 异常处理
- 异常处理链:不同类型的异常由不同的处理器处理
- 错误处理:不同级别的错误由不同的处理器处理
5. 命令处理
- 命令模式与责任链结合:命令的处理链
- 消息处理:消息的路由和处理
6. 其他场景
- 解析器:XML、JSON 等格式的解析器
- 规则引擎:业务规则的处理链
- 工作流系统:工作流节点的处理链
适合使用责任链模式的问题
1. 当一个请求需要经过多个处理步骤时
例如:
- 一个 HTTP 请求需要经过身份验证、权限检查、日志记录等多个步骤
- 一个订单需要经过验证、库存检查、支付处理等多个步骤
2. 当请求的处理者不确定,需要动态确定时
例如:
- 根据用户的角色和权限,动态确定审批流程
- 根据请求的类型和内容,动态确定处理链
3. 当需要避免请求的发送者与接收者之间的耦合时
例如:
- 客户端不需要知道具体的处理者,只需要将请求发送到链头
- 处理者之间不需要知道彼此的存在,只需要处理自己的部分
4. 当需要动态调整处理流程时
例如:
- 根据业务需求,动态添加或删除处理步骤
- 根据配置,动态调整处理顺序
5. 当多个对象都可能处理同一个请求时
例如:
- 多个日志处理器,根据日志级别处理不同的日志
- 多个异常处理器,根据异常类型处理不同的异常
责任链模式的变体
1. 纯责任链 vs 不纯责任链
- 纯责任链:每个处理者要么处理请求,要么将其传递给下一个处理者,不能两者都做
- 不纯责任链:处理者可以处理请求的一部分,然后将其传递给下一个处理者
2. 单向链 vs 环形链
- 单向链:链是线性的,有明确的起点和终点
- 环形链:链是环形的,没有明确的终点,请求会在链中循环直到被处理
3. 静态链 vs 动态链
- 静态链:链的结构在编译时确定
- 动态链:链的结构在运行时动态构建
4. 带返回值的责任链
处理者可以返回处理结果,而不仅仅是处理或传递请求
5. 异步责任链
处理者可以异步处理请求,而不是同步处理
实际应用案例
1. Java Servlet Filter
Java Servlet 中的 Filter 链是责任链模式的典型应用,每个 Filter 可以处理请求或传递给下一个 Filter。
2. Spring Security Filter Chain
Spring Security 中的过滤器链用于处理认证和授权请求。
3. ASP.NET Core Middleware
ASP.NET Core 中的中间件链用于处理 HTTP 请求。
4. Node.js Express Middleware
Express 框架中的中间件链用于处理 HTTP 请求。
5. 日志框架
许多日志框架使用责任链模式来处理不同级别的日志。
代码优化建议
1. 避免过长的链
- 合理设计链的长度,避免链过长影响性能
- 考虑使用组合模式来管理复杂的链结构
2. 确保请求被处理
- 在链的末端添加一个默认处理者,确保所有请求都被处理
- 添加监控和日志,及时发现未被处理的请求
3. 优化链的构建
- 使用工厂方法或构建器模式来构建责任链
- 考虑使用依赖注入来管理处理者的依赖关系
4. 提高可测试性
- 为每个处理者编写单元测试
- 使用模拟对象(Mock)来测试链的行为
- 测试不同的链结构和处理场景
5. 处理异常
- 在处理者中添加异常处理逻辑
- 确保异常不会导致链的中断
总结
责任链模式是一种非常实用的设计模式,它通过将请求沿着处理者链传递,实现了请求发送者和接收者的解耦。责任链模式在事件处理、审批流程、过滤器/拦截器等场景中有着广泛的应用。
通过本文的介绍,相信你已经对责任链模式有了更深入的了解。在实际开发中,当你遇到需要多个处理步骤、动态确定处理者、避免耦合或动态调整处理流程的场景时,不妨考虑使用责任链模式。
记住,设计模式的选择应该基于具体的问题场景,而不是为了使用模式而使用模式。只有在合适的场景中使用合适的设计模式,才能真正发挥其价值。