行为型——责任链模式
责任链模式
责任链模式是一种行为型设计模式,它允许请求沿着处理链传递,直到有一个处理者处理为止。其核心思想是解耦请求发送者与接收者。
特点
- 解耦处理者与接收者: 发送者无需知道哪一个接收者处理请求,接收者也无需知道请求的细节。
- 动态构建处理链: 灵活的调整处理者的顺序或增减处理者。
- 责任明确: 每个处理者只负责处理特定的请求。
模式结构
角色 | 描述 |
---|---|
抽象处理者(Handler) | 定义了处理请求的接口,并且可以访问它的后继者 |
具体处理者(ConcreteHandler) | 实现了处理请求的接口,判断是否可以处理该请求,否则将请求传递给它的后继者 |
客户端(Client) | 创建处理链,并向链的头部发起请求 |
简单示例
from abc import ABC, abstractmethod
from typing import Optional
# 处理者抽象类
class Approver(ABC):
def __init__(self):
self._successor: Optional[Approver] = None
def set_successor(self, successor: 'Approver') -> 'Approver':
self._successor = successor
return successor
@abstractmethod
def handle_request(self, amount: float) -> str:
pass
# 具体处理者类
class Supervisor(Approver):
def handle_request(self, amount: str) -> str:
if amount <= 500:
return f'Supervisor approved ${amount} Reimbursement.'
elif self._successor:
return self._successor.handle_request(amount)
else:
return f'${amount} Reimbursement denied.'
class DepartmentManager(Approver):
def handle_request(self, amount: str) -> str:
if amount <= 1000:
return f'Department Manager approved ${amount} Reimbursement.'
elif self._successor:
return self._successor.handle_request(amount)
else:
return f'${amount} Reimbursement denied.'
class CEO(Approver):
def handle_request(self, amount: str) -> str:
if amount <= 10000:
return f'CEO approved ${amount} Reimbursement.'
elif self._successor:
return self._successor.handle_request(amount)
else:
return f'${amount} Reimbursement denied.'
# 客户端代码
if __name__ == '__main__':
supervisor = Supervisor()
department_manager = DepartmentManager()
ceo = CEO()
supervisor.set_successor(department_manager).set_successor(ceo)
requests = [250, 600, 1250, 10000]
for amount in requests:
print(supervisor.handle_request(amount))
# 结果输出
# Supervisor approved $250.0 Reimbursement.
# Department Manager approved $600.0 Reimbursement.
# CEO approved $1250.0 Reimbursement.
# 10000 Reimbursement denied.
适用场景
- 多级请求处理,如审批流程
- 动态请求处理,如Web框架的中间件
- 需要按优先级处理请求,如客服系统
优缺点
- 优点:
- 减少耦合:处理者与请求者之间解耦,请求者无需知道处理者
- 符合单一职责和开闭原则
- 缺点:
- 请求可能未被处理,需要添加兜底逻辑
- 调试复杂,链条过长时,对象的状态和处理者顺序有关联,需要跟踪整个链条