Python 责任链模式

Python 中的责任链模式(Chain of Responsibility Pattern)

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

形象比喻:就像请假审批——员工先提交给主管,如果主管权限不够,就转给经理;经理不够就转给总监……直到有人能审批或拒绝。

责任链模式的优点

  • 解耦发送者和接收者:客户端无需知道谁来处理请求
  • 动态组合处理链:运行时可以自由添加、移除、重组处理器
  • 单一职责:每个处理器只负责自己能处理的请求
  • 灵活性高:容易扩展新处理器

典型应用场景

  • 日志系统(DEBUG → INFO → WARNING → ERROR 级别)
  • Web 框架中间件(认证 → 授权 → 日志 → 路由 → 响应)
  • 事件处理(如 GUI 事件冒泡)
  • 审批流程(请假、报销)
  • 过滤器链(敏感词过滤、XSS 防御)
  • 异常处理(try-except 链)

Python 实现示例:日志处理器链

我们实现一个分级日志系统:不同级别日志交给不同处理器(控制台、文件、邮件)。

from abc import ABC, abstractmethod

# 抽象处理器(Handler)
class Logger(ABC):
    def __init__(self, next_logger=None):
        self.next_logger = next_logger  # 链中的下一个处理器

    def log(self, level: int, message: str):
        if self.can_handle(level):
            self.handle(message)
        # 如果有下一个处理器,继续传递
        if self.next_logger:
            self.next_logger.log(level, message)

    @abstractmethod
    def can_handle(self, level: int) -> bool:
        pass

    @abstractmethod
    def handle(self, message: str):
        pass

# 日志级别常量
DEBUG = 1
INFO = 2
WARNING = 3
ERROR = 4

# 具体处理器1:控制台日志(处理所有级别)
class ConsoleLogger(Logger):
    def can_handle(self, level: int) -> bool:
        return True  # 所有日志都打印到控制台

    def handle(self, message: str):
        print(f"[CONSOLE] {message}")

# 具体处理器2:文件日志(只处理 WARNING 及以上)
class FileLogger(Logger):
    def can_handle(self, level: int) -> bool:
        return level >= WARNING

    def handle(self, message: str):
        print(f"[FILE] 写入日志文件: {message}")

# 具体处理器3:邮件通知(只处理 ERROR 级别)
class EmailLogger(Logger):
    def can_handle(self, level: int) -> bool:
        return level == ERROR

    def handle(self, message: str):
        print(f"[EMAIL] 发送紧急邮件通知: {message}")

# 构建责任链
def build_chain():
    # 链顺序:控制台 → 文件 → 邮件
    email_logger = EmailLogger()
    file_logger = FileLogger(email_logger)
    console_logger = ConsoleLogger(file_logger)
    return console_logger

# 客户端使用
if __name__ == "__main__":
    logger_chain = build_chain()

    logger_chain.log(DEBUG, "系统启动正常")          # 只控制台
    logger_chain.log(INFO, "用户登录成功")           # 只控制台
    logger_chain.log(WARNING, "磁盘空间不足")       # 控制台 + 文件
    logger_chain.log(ERROR, "数据库连接失败!")      # 控制台 + 文件 + 邮件

输出

[CONSOLE] 系统启动正常
[CONSOLE] 用户登录成功
[CONSOLE] 磁盘空间不足
[FILE] 写入日志文件: 磁盘空间不足
[CONSOLE] 数据库连接失败!
[FILE] 写入日志文件: 数据库连接失败!
[EMAIL] 发送紧急邮件通知: 数据库连接失败!

Pythonic 更简洁实现:函数式责任链

Python 支持高阶函数,可以用列表+循环实现轻量责任链。

from typing import Callable, List

# 定义处理器类型
Handler = Callable[[str], bool]  # 返回 True 表示已处理,不再向下传递

def console_handler(message: str) -> bool:
    print(f"[CONSOLE] {message}")
    return False  # 继续向下传递

def file_handler(message: str) -> bool:
    if "错误" in message or "警告" in message:
        print(f"[FILE] 记录严重日志: {message}")
    return False

def email_handler(message: str) -> bool:
    if "致命" in message or "失败" in message:
        print(f"[EMAIL] 紧急通知: {message}")
        return True  # 已处理,停止传递
    return False

# 构建链
handlers: List[Handler] = [console_handler, file_handler, email_handler]

def log_message(message: str):
    for handler in handlers:
        if handler(message):
            break  # 某个处理器返回 True,停止链

# 使用
log_message("程序启动")
log_message("用户登录")
log_message("内存警告")
log_message("数据库连接失败")

真实项目常见例子:Web 框架中间件

Flask/Django/FastAPI 的中间件本质就是责任链:

class Middleware:
    def __init__(self, next_middleware=None):
        self.next = next_middleware

    def __call__(self, request):
        # 前置处理
        self.process_request(request)
        # 传递给下一个
        if self.next:
            response = self.next(request)
        else:
            response = handle_request(request)  # 最终处理
        # 后置处理
        return self.process_response(response)

class AuthMiddleware(Middleware):
    def process_request(self, request):
        if not request.user.is_authenticated:
            return redirect("/login")

class LoggingMiddleware(Middleware):
    def process_request(self, request):
        print(f"请求: {request.path}")

# 构建链:Logging → Auth → 最终处理
app = LoggingMiddleware(AuthMiddleware())

责任链模式结构总结

角色说明
Handler抽象处理器(Logger),定义处理接口和链指针
ConcreteHandler具体处理器(ConsoleLogger 等)
Client发送请求到链首(logger_chain.log())

责任链模式 vs 其他模式对比

模式目的处理方式典型场景
责任链请求沿链传递,直到被处理动态链、可能不处理中间件、日志、审批
装饰器层层增强功能固定链、全部执行功能包装
命令封装请求为对象支持队列、撤销操作历史
观察者广播通知多个对象一对多广播事件系统

Python 中的实用建议

  • 简单场景:用函数列表实现(最轻量)
  • 复杂场景:用类实现,支持状态和动态重组
  • 停止传递:处理器返回 True/None/Response 表示是否终止链
  • 常见库实现
  • Django 中间件
  • Flask 的 @app.before_request
  • FastAPI 的 Dependencies 和 Middlewares

注意事项

  • 确保链的顺序正确(优先级高的放前面)
  • 避免循环链(会导致无限递归)
  • 如果没有处理器处理请求,要有默认行为(否则请求丢失)
  • 多线程时注意线程安全

责任链模式是构建可插拔、可扩展处理流程的利器,在 Web 框架、日志系统、过滤器中无处不在。

如果你想看更多实战例子(如 HTTP 请求中间件链、审批流程系统、敏感词过滤链),或者如何与装饰器模式结合,欢迎继续问!

文章已创建 3511

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部