Python 责任链模式
Python 责任链模式 责任链模式是一种行为设计模式,它允许你将请求沿着处理链进行传递。收到请求后,每个处理者都可以对请求进行处理,或者将其传递给链上的下一个处理者。 生活中的类比 想象一下公司里的请假审批流程: 1-3 天 → 组长审批 4-7 天 → 部门经理审批 8 天以上 → 总经理审批 当你提交请假申请时,申请会按照这个链条依次传递,直到找到有权限处理的人。这就是责任链模式的现实体现。 模式的核心思想 责任链模式的..
教程详情页默认 noindex。
Python 责任链模式
责任链模式是一种行为设计模式,它允许你将请求沿着处理链进行传递。收到请求后,每个处理者都可以对请求进行处理,或者将其传递给链上的下一个处理者。
生活中的类比
想象一下公司里的请假审批流程:
- 1-3 天 → 组长审批
- 4-7 天 → 部门经理审批
- 8 天以上 → 总经理审批
当你提交请假申请时,申请会按照这个链条依次传递,直到找到有权限处理的人。这就是责任链模式的现实体现。
模式的核心思想
责任链模式的核心在于解耦请求的发送者和接收者,让多个对象都有机会处理请求,从而避免请求发送者与接收者之间的紧密耦合。
责任链模式的结构
让我们通过 UML 类图来理解责任链模式的组成结构:

核心组件说明
Handler(抽象处理者)
- 定义处理请求的接口
- 包含设置后继者的方法
- 可以实现后继链的默认行为
ConcreteHandler(具体处理者)
- 实现具体的处理逻辑
- 如果可以处理请求,就进行处理
- 否则将请求转发给后继者
基础实现:请假审批系统
让我们用 Python 实现一个简单的请假审批系统来理解责任链模式。
步骤 1:定义抽象处理者
实例
from typing import Optional
class Approver(ABC):
"""审批者抽象类"""
def __init__(self, name: str):
self.name = name
self.successor: Optional['Approver'] = None
def set_successor(self, successor: 'Approver'):
"""设置后继审批者"""
self.successor = successor
@abstractmethod
def process_request(self, leave_request: 'LeaveRequest'):
"""处理请假请求的抽象方法"""
pass
步骤 2:定义请求对象
实例
@dataclass
class LeaveRequest:
"""请假请求数据类"""
employee_name: str # 员工姓名
leave_days: int # 请假天数
reason: str # 请假原因
def __str__(self):
return f"{self.employee_name} 申请请假 {self.leave_days} 天,原因:{self.reason}"
步骤 3:实现具体处理者
实例
"""组长 - 处理 1-3 天的请假"""
def process_request(self, leave_request: LeaveRequest):
if leave_request.leave_days <= 3:
print(f"组长 {self.name} 批准了 {leave_request}")
elif self.successor is not None:
# 超出权限,传递给下一级
print(f"组长 {self.name} 无权限,转交给上级处理")
self.successor.process_request(leave_request)
else:
print("无法处理该请求:没有合适的审批者")
class DepartmentManager(Approver):
"""部门经理 - 处理 4-7 天的请假"""
def process_request(self, leave_request: LeaveRequest):
if 4 <= leave_request.leave_days <= 7:
print(f"部门经理 {self.name} 批准了 {leave_request}")
elif self.successor is not None:
# 超出权限,传递给下一级
print(f"部门经理 {self.name} 无权限,转交给上级处理")
self.successor.process_request(leave_request)
else:
print("无法处理该请求:没有合适的审批者")
class GeneralManager(Approver):
"""总经理 - 处理 8 天以上的请假"""
def process_request(self, leave_request: LeaveRequest):
if leave_request.leave_days >= 8:
print(f"总经理 {self.name} 批准了 {leave_request}")
else:
print("无法处理该请求:请假天数不符合要求")
步骤 4:构建责任链并测试
实例
# 创建审批者
team_leader = TeamLeader("张三")
dept_manager = DepartmentManager("李四")
general_manager = GeneralManager("王五")
# 构建责任链:组长 → 部门经理 → 总经理
team_leader.set_successor(dept_manager)
dept_manager.set_successor(general_manager)
# 创建测试用例
test_cases = [
LeaveRequest("小明", 2, "感冒发烧"),
LeaveRequest("小红", 5, "回家探亲"),
LeaveRequest("小刚", 10, "结婚休假"),
LeaveRequest("小李", 15, "出国旅游")
]
print("=== 请假审批测试 ===\n")
# 处理所有请假请求
for request in test_cases:
print(f"处理请求: {request.employee_name} 请假 {request.leave_days} 天")
team_leader.process_request(request)
print("-" * 50)
if __name__ == "__main__":
main()
运行结果
=== 请假审批测试 === 处理请求: 小明 请假 2 天 组长 张三 批准了 小明 申请请假 2 天,原因:感冒发烧 -------------------------------------------------- 处理请求: 小红 请假 5 天 组长 张三 无权限,转交给上级处理 部门经理 李四 批准了 小红 申请请假 5 天,原因:回家探亲 -------------------------------------------------- 处理请求: 小刚 请假 10 天 组长 张三 无权限,转交给上级处理 部门经理 李四 无权限,转交给上级处理 总经理 王五 批准了 小刚 申请请假 10 天,原因:结婚休假 -------------------------------------------------- 处理请求: 小李 请假 15 天 组长 张三 无权限,转交给上级处理 部门经理 李四 无权限,转交给上级处理 总经理 王五 批准了 小李 申请请假 15 天,原因:出国旅游 --------------------------------------------------
高级应用:Web 请求过滤器
责任链模式在 Web 开发中非常常见,特别是在中间件和过滤器链中。让我们实现一个简单的 HTTP 请求过滤器链。
步骤 1:定义请求和响应对象
实例
from typing import Dict, Any
@dataclass
class HttpRequest:
"""HTTP 请求对象"""
method: str
path: str
headers: Dict[str, str]
body: Any = None
user: Dict[str, Any] = None
@dataclass
class HttpResponse:
"""HTTP 响应对象"""
status_code: int
headers: Dict[str, str]
body: Any = None
步骤 2:实现过滤器链
实例
"""过滤器抽象类"""
def __init__(self):
self.next_filter: Optional['Filter'] = None
def set_next(self, next_filter: 'Filter'):
"""设置下一个过滤器"""
self.next_filter = next_filter
def do_filter(self, request: HttpRequest, response: HttpResponse) -> bool:
"""
执行过滤操作
返回 True 表示继续执行,False 表示中断
"""
if self.handle(request, response):
if self.next_filter is not None:
return self.next_filter.do_filter(request, response)
return True
return False
@abstractmethod
def handle(self, request: HttpRequest, response: HttpResponse) -> bool:
"""具体的过滤处理逻辑"""
pass
class AuthenticationFilter(Filter):
"""身份认证过滤器"""
def handle(self, request: HttpRequest, response: HttpResponse) -> bool:
print("执行身份认证...")
# 模拟认证逻辑
token = request.headers.get('Authorization')
if token == "Bearer valid-token":
request.user = {"id": 1, "name": "张三", "role": "user"}
print("✓ 身份认证成功")
return True
else:
response.status_code = 401
response.body = {"error": "未授权的访问"}
print("✗ 身份认证失败")
return False
class LoggingFilter(Filter):
"""日志记录过滤器"""
def handle(self, request: HttpRequest, response: HttpResponse) -> bool:
print(f"记录请求日志: {request.method} {request.path}")
return True # 总是继续执行
class PermissionFilter(Filter):
"""权限检查过滤器"""
def handle(self, request: HttpRequest, response: HttpResponse) -> bool:
print("检查用户权限...")
if request.user and request.user.get('role') == 'admin':
print("✓ 权限检查通过")
return True
else:
response.status_code = 403
response.body = {"error": "权限不足"}
print("✗ 权限检查失败")
return False
步骤 3:使用过滤器链处理请求
实例
"""处理 HTTP 请求"""
# 创建默认响应
response = HttpResponse(
status_code=200,
headers={"Content-Type": "application/json"},
body={"message": "请求成功"}
)
# 创建过滤器链
auth_filter = AuthenticationFilter()
logging_filter = LoggingFilter()
permission_filter = PermissionFilter()
# 构建过滤器链:日志 → 认证 → 权限
logging_filter.set_next(auth_filter)
auth_filter.set_next(permission_filter)
# 执行过滤器链
print("开始处理 HTTP 请求...")
logging_filter.do_filter(request, response)
print("请求处理完成")
return response
# 测试不同的请求场景
def test_filter_chain():
print("=== HTTP 过滤器链测试 ===\n")
# 测试用例 1:有效的管理员请求
print("测试用例 1:有效的管理员请求")
request1 = HttpRequest(
method="GET",
path="/admin/data",
headers={"Authorization": "Bearer valid-token"}
)
response1 = process_http_request(request1)
print(f"响应状态码: {response1.status_code}")
print(f"响应内容: {response1.body}\n")
# 测试用例 2:未授权的请求
print("测试用例 2:未授权的请求")
request2 = HttpRequest(
method="GET",
path="/admin/data",
headers={"Authorization": "Bearer invalid-token"}
)
response2 = process_http_request(request2)
print(f"响应状态码: {response2.status_code}")
print(f"响应内容: {response2.body}\n")
if __name__ == "__main__":
test_filter_chain()
责任链模式的优缺点
优点
1. 降低耦合度
请求发送者不需要知道哪个对象会处理它的请求,接收者也不需要知道请求的全貌。
2. 增强灵活性
可以动态地添加、删除或重新排列处理者,而不影响客户端代码。
3. 简化对象职责
每个处理者只需关注自己职责范围内的请求,符合单一职责原则。
4. 便于扩展
新增处理者非常容易,只需要实现处理接口并添加到链中即可。
缺点
1. 请求可能未被处理
如果责任链配置不当,请求可能到达链的末端而没有被任何处理者处理。
2. 性能考虑
较长的责任链可能会影响性能,特别是在处理大量请求时。
3. 调试困难
请求的处理路径可能不明确,调试时难以跟踪请求的完整处理流程。
实际应用场景
1. 事件处理系统
图形界面中的事件冒泡机制就是责任链模式的典型应用。
实例
def __init__(self, name, target):
self.name = name
self.target = target
self.handled = False
class Widget:
def __init__(self, parent=None):
self.parent = parent
def handle_event(self, event):
# 先自己处理,如果处理不了就传递给父组件
if self.on_event(event):
event.handled = True
elif self.parent:
self.parent.handle_event(event)
def on_event(self, event):
# 子类重写这个方法来实现具体的事件处理
return False
2. 日志系统
不同级别的日志消息由不同的处理器处理。
实例
# 创建日志记录器
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 创建处理器链
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler('app.log')
# 设置处理器级别
console_handler.setLevel(logging.WARNING)
file_handler.setLevel(logging.DEBUG)
# 添加到记录器
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 使用:DEBUG 和 INFO 级别只会记录到文件,WARNING 及以上会同时输出到控制台
logger.debug('调试信息') # 只记录到文件
logger.warning('警告信息') # 同时输出到控制台和文件
最佳实践和注意事项
1. 设置默认处理行为
确保责任链的末端有一个默认处理者,避免请求丢失。
实例
"""默认处理者 - 处理所有未被处理的请求"""
def process_request(self, leave_request: LeaveRequest):
print(f"默认处理者:无法处理 {leave_request},请检查请求参数")
2. 控制链的长度
避免创建过长的责任链,这会降低性能并增加调试难度。
3. 明确的处理规则
确保每个处理者都有清晰的处理边界,避免职责重叠。
4. 考虑使用组合模式
对于复杂的责任链,可以考虑使用组合模式来管理处理者之间的关系。
总结
责任链模式是一个强大而灵活的设计模式,它通过将请求的发送者和接收者解耦,提供了一种优雅的方式来处理需要多个对象协作的场景。
关键要点
- 核心思想:让多个对象都有机会处理请求,避免请求发送者与接收者的耦合
- 适用场景:多个对象可以处理同一请求,但具体由哪个对象处理需要在运行时确定
- 实现要点:定义处理接口、构建处理链、传递请求
- Python 特色:利用 Python 的动态特性,可以更灵活地实现责任链模式