责任链模式(Chain of Responsibility Pattern)
定义
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
设计的原则和思想
- 解耦的是请求发送对象(触发业务的对象)和请求处理对象(处理业务的对象)。
- 不变部分是请求处理对象,变化部分是请求处理对象之间的关系。
- 核心思想是 将请求处理对象之间的关系,从一对多的关系,转化成链型关系。
一句话概括设计模式
多个处理者连接成一条链,并且各自承担各自的处理职责。
结构中包含的角色
- Handler(抽象处理者)
- ConcreteHandler(具体处理者)
最小可表达代码
abstract class Handler
{
protected $nextHandler;
public function setNextHandler(Handler $nextHandler)
{
$this->nextHandler = $nextHandler;
}
public abstract function handleRequest(String $request);
}
class ConcreteHandler extends Handler
{
public function handleRequest(String $request)
{
// 判断当前请求是否需要转发
$isForward = false;
if (! $isForward) {
// 自身业务处理
var_dump('业务处理' . $request);
// 二次判断是否需要转发
$isForward = true;
}
if ($isForward && $this->nextHandler) {
$this->nextHandler->handleRequest($request); //转发请求
}
}
}
$request = 'test';
$handler1 = new ConcreteHandler();
$handler2 = new ConcreteHandler();
$handler1->setNextHandler($handler2);
$handler1->handleRequest($request);
优点
- 一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可。
- 把请求处理对象之间的关系,从一对多的关系,转化成一对一的关系。简化了对象之间的相互连接的关系。
- 你可以控制请求处理的顺序。
- 增加新的请求处理类很方便。
缺点
- 不能保证请求一定被处理。
- 长的职责链,性能会有一定影响,调试代码也不太方便。
- 建链代码复杂。
何时使用
- 多个对象处理同一个请求。
- 需要使用不同方式处理不同请求。
- 需要按顺序执行多个处理者时。
- 需要处理者及其顺序必须在运行时进行改变。
实际应用场景
- 过滤这些敏感词。
- JS 中的事件冒泡。
- 工作流中的分级审批。
纯的职责链模式和不纯的职责链模式
纯的职责链模式
要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。
而且在纯的职责链模式中,要求一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况。
不纯的职责链模式
在一个不纯的职责链模式中允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后其后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。