21 PHP 设计模式系列「责任链模式(Chain )」

2022-10-11 20:36:25 195 0
魁首哥

1、模式定义

责任链模式 将处理请求的对象连成一条链,沿着这条链传递该请求,直到有一个对象处理请求为止,这使得多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。

责任链模式在现实中使用的很多,常见的就是 OA 系统中的工作流。

2、UML 类图

3、示例代码

Request.php

整型数据 或者一个数组即可。
 * 但是作为一个完整示例,这里我们生成了一个请求类。
 * 在实际项目中,也推荐使用请求类,即是是一个标准类\stdClass,
 * 因为这样的话代码更具扩展性,因为责任链的处理器并不了解外部世界,
 * 如果某天你想要添加其它复杂处理时不使用请求类会很麻烦
 */
class Request
{
 // getter and setter but I don't want to generate too much noise in handlers
}
 

Handler.php

successor)) {
 $this->successor = $handler;
 } else {
 $this->successor->append($handler);
 }
 }
 /**
 * 处理请求
 *
 * 这里我们使用模板方法模式以确保每个子类都不会忘记调用successor
 * 此外,返回的布尔值表明请求是否被处理
 * 
 * @param Request $req
 *
 * @return bool
 */
 final public function handle(Request $req)
 {
 $req->forDebugOnly = get_called_class();
 $processed = $this->processing($req);
 if (!$processed) {
 // the request has not been processed by this handler => see the next
 if (!is_null($this->successor)) {
 $processed = $this->successor->handle($req);
 }
 }
 return $processed;
 }
 /**
 * 每个处理器具体实现类都要实现这个方法对请求进行处理
 *
 * @param Request $req
 *
 * @return bool true if the request has been processed
 */
 abstract  protected  function processing(Request $req);
}
 

Responsible/SlowStorage.php

data = $data;
 }
 protected function processing(Request $req)
 {
 if ('get' === $req->verb) {
 if (array_key_exists($req->key, $this->data)) {
 $req->response = $this->data[$req->key];
 return true;
 }
 }
 return false;
 }
}
 

Responsible/FastStorage.php

data = $data;
 }
 protected function processing(Request $req)
 {
 if ('get' === $req->verb) {
 if (array_key_exists($req->key, $this->data)) {
 $req->response = $this->data[$req->key];
 return true;
 }
 }
 return false;
 }
}
 

4、测试代码

Tests/ChainTest.php

chain = new FastStorage(array('bar' => 'baz'));
 $this->chain->append(new SlowStorage(array('bar' => 'baz', 'foo' => 'bar')));
 }
 public function makeRequest()
 {
 $request = new Request();
 $request->verb = 'get';
 return array(
 array($request)
 );
 }
 /**
 * @dataProvider makeRequest
 */
 public function testFastStorage($request)
 {
 $request->key = 'bar';
 $ret = $this->chain->handle($request);
 $this->assertTrue($ret);
 $this->assertObjectHasAttribute('response', $request);
 $this->assertEquals('baz', $request->response);
 // despite both handle owns the 'bar' key, the FastStorage is responding first
 $className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\FastStorage';
 $this->assertEquals($className, $request->forDebugOnly);
 }
 /**
 * @dataProvider makeRequest
 */
 public function testSlowStorage($request)
 {
 $request->key = 'foo';
 $ret = $this->chain->handle($request);
 $this->assertTrue($ret);
 $this->assertObjectHasAttribute('response', $request);
 $this->assertEquals('bar', $request->response);
 // FastStorage has no 'foo' key, the SlowStorage is responding
 $className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage';
 $this->assertEquals($className, $request->forDebugOnly);
 }
 /**
 * @dataProvider makeRequest
 */
 public function testFailure($request)
 {
 $request->key = 'kurukuku';
 $ret = $this->chain->handle($request);
 $this->assertFalse($ret);
 // the last responsible :
 $className = 'DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowStorage';
 $this->assertEquals($className, $request->forDebugOnly);
 }
}
 

5、总结

责任链模式的主要优点在于可以降低系统的耦合度,简化对象的相互连接,同时增强给对象指派职责的灵活性,增加新的请求处理类也很方便;其主要缺点在于不能保证请求一定被接收,且对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。

收藏
分享
海报
0 条评论
195
上一篇:PHP程序员必看:ThinkPHP5.0 自定义命令行的使用 下一篇:php有多态吗 多态都有什么好处?理解好多态往往能事半功倍

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码