6、责任链模式
6、责任链模式
一、定义
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。这种模式特别适用于那些需要通过多个步骤来处理请求的情况,并且这些步骤可以动态地添加、移除或重新排序。
在某些系统中,可能存在一系列连续的检查或者处理步骤,例如在线订购系统的权限验证、数据清理、IP地址过滤以及缓存检查等。随着新功能的不断加入,代码可能会变得越来越复杂和难以维护。责任链模式提供了一种解决方案,它可以将这些处理步骤抽象为独立的对象,并将它们连接成一条链,从而简化了代码结构并提高了其可读性和可维护性。
二、责任链模式结构
处理者 (Handler) 声明了所有具体处理者的通用接口。 该接口通常仅包含单个方法用于请求处理, 但有时其还会包含一个设置链上下个处理者的方法。
基础处理者 (Base Handler) 是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。
通常情况下, 该类中定义了一个保存对于下个处理者引用的成员变量。 客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。 该类还可以实现默认的处理行为: 确定下个处理者存在后再将请求传递给它。
具体处理者 (Concrete Handlers) 包含处理请求的实际代码。 每个处理者接收到请求后, 都必须决定是否进行处理, 以及是否沿着链传递请求。
三、实现方式
**方式一:**其中第一种方式是在设计模式这本书中学习的,这种模式是先指定具体的处理者。例如处理数据(pandas)先fillna->sum->count,类似于pandas中的pipeline。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Optional
class Handler(ABC):
@abstractmethod
def set_next(self, handler: Handler) -> Handler:
pass
@abstractmethod
def handle(self, request) -> Optional[str]:
pass
class AbstractHandler(Handler):
_next_handler: Handler = None
def set_next(self, handler: Handler) -> Handler:
self._next_handler = handler
return handler
@abstractmethod
def handle(self, request: Any):
if self._next_handler:
return self._next_handler.handle(request)
return None
class MonkeyHandler(AbstractHandler):
def handle(self, request: Any) -> str:
if request == "Banana":
return f"Monkey: I'll eat the {request}"
else:
return super().handle(request)
class SquirrelHandler(AbstractHandler):
def handle(self, request: Any) -> str:
if request == "Nut":
return f"Squirrel: I'll eat the {request}"
else:
return super().handle(request)
class DogHandler(AbstractHandler):
def handle(self, request: Any) -> str:
if request == "MeatBall":
return f"Dog: I'll eat the {request}"
else:
return super().handle(request)
def client_code(handler: Handler) -> None:
for food in ["Nut", "Banana", "Cup of coffee"]:
print(f"\nClient: Who wants a {food}?")
result = handler.handle(food)
if result:
print(f" {result}", end="")
else:
print(f" {food} was left untouched.", end="")
方式二,这种方式是在B站中学习的,它是已经确定了责任链的next,但是个人感觉缺少了代码的灵活性,适合比较固定模式的方式。
from abc import ABC, abstractmethod
class AskLeave(ABC):
@abstractmethod
def furlough(self, day):
pass
class PL(AskLeave):
def furlough(self, day):
if day <= 1:
print('准假')
else:
PM().furlough(day)
class PM(AskLeave):
def furlough(self, day):
if day <= 3:
print('准假')
else:
Manger().furlough(day)
class Manger(AskLeave):
def furlough(self, day):
if day <= 10:
print('准假')
else:
print('离职吧')
四、优缺点
优点
- **解耦:**降低了请求发送者与接收者之间的耦合度,使两者不必直接相互依赖。
- **灵活性:**可以方便地添加或删除处理者,甚至改变它们的顺序,而无需修改其他部分的代码。
- **可扩展性:**支持轻松地引入新的处理逻辑,符合开闭原则。
缺点
当然,责任链模式也有一些潜在的缺点:
- 如果责任链太长或处理时间过长,可能会影响性能。
- 当责任链未正确配置时,存在请求未被任何处理器处理的风险。
- 对于较长的责任链,调试可能会变得较为困难。