php责任链模式的订单,责任链模式(Chain Of Responsibilities)

3.1.1. 目的

建立一个对象链来按指定顺序处理调用。如果其中一个对象无法处理命令,它会委托这个调用给它的下一个对象来进行处理,以此类推。

3.1.2. 例子

日志框架,每个链元素自主决定如何处理日志消息。

垃圾邮件过滤器。

缓存:例如第一个对象是一个 Memcached 接口实例,如果 “丢失” 它会委托数据库接口处理这个调用。

Yii 框架: CFilterChain 是一个控制器行为过滤器链。执行点会有链上的过滤器逐个传递,并且只有当所有的过滤器验证通过,这个行为最后才会被调用。

3.1.3. UML 图

7bdae7540cf1a3f6dcb7b46b198a1f6b.png

3.1.4. 代码

你也可以在 GitHub 上查看此代码

Handler.php

namespace DesignPatterns\Behavioral\ChainOfResponsibilities;

use Psr\Http\Message\RequestInterface;

use Psr\Http\Message\ResponseInterface;

/**

* 创建处理器抽象类 Handler 。

*/

abstract class Handler

{

/**

* @var Handler|null

* 定义继承处理器

*/

private $successor = null;

/**

* 输入集成处理器对象。

*/

public function __construct(Handler $handler = null)

{

$this->successor = $handler;

}

/**

* 通过使用模板方法模式这种方法可以确保每个子类不会忽略调用继

* 承。

*

* @param RequestInterface $request

* 定义处理请求方法。

*

* @return string|null

*/

final public function handle(RequestInterface $request)

{

$processed = $this->processing($request);

if ($processed === null) {

// 请求尚未被目前的处理器处理 => 传递到下一个处理器。

if ($this->successor !== null) {

$processed = $this->successor->handle($request);

}

}

return $processed;

}

/**

* 声明处理方法。

*/

abstract protected function processing(RequestInterface $request);

}

Responsible/FastStorage.php

namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;

use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;

use Psr\Http\Message\RequestInterface;

/**

* 创建 http 缓存处理类。

*/

class HttpInMemoryCacheHandler extends Handler

{

/**

* @var array

*/

private $data;

/**

* @param array $data

* 传入数据数组参数。

* @param Handler|null $successor

* 传入处理器类对象 $successor 。

*/

public function __construct(array $data, Handler $successor = null)

{

parent::__construct($successor);

$this->data = $data;

}

/**

* @param RequestInterface $request

* 传入请求类对象参数 $request 。

* @return string|null

*

* 返回缓存中对应路径存储的数据。

*/

protected function processing(RequestInterface $request)

{

$key = sprintf(

'%s?%s',

$request->getUri()->getPath(),

$request->getUri()->getQuery()

);

if ($request->getMethod() == 'GET' && isset($this->data[$key])) {

return $this->data[$key];

}

return null;

}

}

Responsible/SlowStorage.php

namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible;

use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;

use Psr\Http\Message\RequestInterface;

/**

* 创建数据库处理器。

*/

class SlowDatabaseHandler extends Handler

{

/**

* @param RequestInterface $request

* 传入请求类对象 $request 。

*

* @return string|null

* 定义处理方法,下面应该是个数据库查询动作,但是简单化模拟,直接返回一个 'Hello World' 字符串作查询结果。

*/

protected function processing(RequestInterface $request)

{

// 这是一个模拟输出, 在生产代码中你应该调用一个缓慢的 (相对于内存来说) 数据库查询结果。

return 'Hello World!';

}

}

3.1.5. 测试

Tests/ChainTest.php

namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;

use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;

use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\HttpInMemoryCacheHandler;

use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowDatabaseHandler;

use PHPUnit\Framework\TestCase;

/**

* 创建一个自动化测试单元 ChainTest 。

*/

class ChainTest extends TestCase

{

/**

* @var Handler

*/

private $chain;

/**

* 模拟设置缓存处理器的缓存数据。

*/

protected function setUp()

{

$this->chain = new HttpInMemoryCacheHandler(

['/foo/bar?index=1' => 'Hello In Memory!'],

new SlowDatabaseHandler()

);

}

/**

* 模拟从缓存中拉取数据。

*/

public function testCanRequestKeyInFastStorage()

{

$uri = $this->createMock('Psr\Http\Message\UriInterface');

$uri->method('getPath')->willReturn('/foo/bar');

$uri->method('getQuery')->willReturn('index=1');

$request = $this->createMock('Psr\Http\Message\RequestInterface');

$request->method('getMethod')

->willReturn('GET');

$request->method('getUri')->willReturn($uri);

$this->assertEquals('Hello In Memory!', $this->chain->handle($request));

}

/**

* 模拟从数据库中拉取数据。

*/

public function testCanRequestKeyInSlowStorage()

{

$uri = $this->createMock('Psr\Http\Message\UriInterface');

$uri->method('getPath')->willReturn('/foo/baz');

$uri->method('getQuery')->willReturn('');

$request = $this->createMock('Psr\Http\Message\RequestInterface');

$request->method('getMethod')

->willReturn('GET');

$request->method('getUri')->willReturn($uri);

$this->assertEquals('Hello World!', $this->chain->handle($request));

}

}

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接

我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值