责任链模式
情景
建立一个对象链,按照指定顺序处理调用;如果其中有一个对象无法处理当前的情况,移交下一个对象处理
例子
- 日志框架,每个链元素自主决定如何处理日志消息。
- 垃圾邮件过滤器。
- 缓存:例如第一个对象是一个 Memcached 接口实例,如果 “丢失” 它会委托数据库接口处理这个调用。
- 举报处理系统
PHP代码
- 创建处理器抽象类
namespace ChainOfResponsibilities;
/**
* handler 抽象类
* Class Handler
* @package ChainOfResponsibilities
*/
abstract class Handler
{
/**
* 定义下一级处理对象
* @var null
*/
private $successor = null;
/**
* 输入集成处理对象
* Handler constructor.
* @param Handler|null $handler
*/
public function __construct(Handler $handler = null)
{
$this->successor = $handler;
}
/**
* 通过使用模板方法模式这种方法可以确保每个子类不会忽略调用继承
*
* @param int $request
* @return mixed
*/
final public function handle(int $request)
{
$processed = $this->processing($request);
if ($processed ===null) {
// 请求尚未被目前的处理器处理 => 传递到下一个处理器。
if ($this->successor !== null) {
$processed = $this->successor->processing($request);
}
}
return $processed;
}
abstract protected function processing(int $request);
}
- 具体的处理类1
namespace ChainOfResponsibilities;
class ConcreteHandler1 extends Handler
{
/**
* 处理
* @param int $request
* @return $this|null
*/
protected function processing(int $request)
{
if ($request < 0) {
echo "当前对象1:举报处理完毕" . '<br>';
return $this;
}
return null;
}
}
- 具体的处理类2
namespace ChainOfResponsibilities;
class ConcreteHandler2 extends Handler
{
protected function processing(int $request)
{
if ($request > 0) {
echo "当前对象2:举报处理完毕" . '<br>';
return $this;
}
return null;
}
}
- 实施调用
<?php
use ChainOfResponsibilities\ConcreteHandler1;
use ChainOfResponsibilities\ConcreteHandler2;
// 注册自加载
spl_autoload_register(function ($class) {
require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php';
});
//设置责任链上下家
$handler1 = new ConcreteHandler1(new ConcreteHandler2());
$request = [1, -1, 2];
foreach ($request as $value) {
$handler1->handle($value);
}
//输出结果
当前对象2:举报处理完毕
当前对象1:举报处理完毕
当前对象2:举报处理完毕
总结
- 职责链模式, 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对像处理它为止。
- 接受者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个向其后继者的引用,而不需要保持它所有的候选者的引用。
网友评论