PHP设计模式之责任链模式的深入解析


Posted in PHP onJune 13, 2013

责任链模式,其目的是组织一个对象链处理一个如方法调用的请求。
当ConcreteHandler(具体的处理程序)不知道如何满足来自Client的请求时,或它的目的不是这个时,它会委派给链中的下一个Handler(处理程序)来处理。

这个设计模式通常和复合模式一起使用,其中有些叶子或容器对象默认委派操作给它们的父对象。另一个例子是,本地化通常是使用责任链处理的,当德语翻译适配器没有为翻译关键词找到合适的结果时,就返回到英语适配器或干脆直接显示关键词本身。

耦合减少到最低限度:Client类不知道由哪个具体的类来处理请求;在创建对象图时配置了链;ConcreteHandlers不知道哪个对象是它们的继承者。行为在对象之间分配是成功的,链中最近的对象有优先权和责任满足请求。

参与者:
◆Client(客户端):向Handler(处理程序)提交一个请求;
◆Handler(处理程序)抽象:接收一个请求,以某种方式满足它;
◆ConcreteHandlers(具体的处理程序):接收一个请求,设法满足它,如果不成功就委派给下一个处理程序。
下面的代码实现了一个最著名的责任链示例:多级缓存。

/**  
 * The Handler abstraction. Objects that want to be a part of the  
 * ChainOfResponsibility must implement this interface directly or via  
 * inheritance from an AbstractHandler.  
 */ 
interface KeyValueStore  
{  
    /**  
     * Obtain a value.  
     * @param string $key  
     * @return mixed  
     */ 
    public function get($key);  
}  /**  
 * Basic no-op implementation which ConcreteHandlers not interested in  
 * caching or in interfering with the retrieval inherit from.  
 */ 
abstract class AbstractKeyValueStore implements KeyValueStore  
{  
    protected $_nextHandler;  
    public function get($key)  
    {  
 return $this->_nextHandler->get($key);  
    }  
}  
/**  
 * Ideally the last ConcreteHandler in the chain. At least, if inserted in  
 * a Chain it will be the last node to be called.  
 */ 
class SlowStore implements KeyValueStore  
{  
    /**  
     * This could be a somewhat slow store: a database or a flat file.  
     */ 
    protected $_values;  
    public function __construct(array $values = array())  
    {  
 $this->_values = $values;  
    }  
    public function get($key)  
    {  
 return $this->_values[$key];  
    }  
}  
/**  
 * A ConcreteHandler that handles the request for a key by looking for it in  
 * its own cache. Forwards to the next handler in case of cache miss.  
 */ 
class InMemoryKeyValueStore implements KeyValueStore  
{  
    protected $_nextHandler;  
    protected $_cached = array();  
    public function __construct(KeyValueStore $nextHandler)  
    {  
 $this->_nextHandler = $nextHandler;  
    }  
    protected function _load($key)  
    {  
 if (!isset($this->_cached[$key])) {  
     $this->_cached[$key] = $this->_nextHandler->get($key);  
 }  
    }  
    public function get($key)  
    {  
 $this->_load($key);  
 return $this->_cached[$key];  
    }  
}  
/**  
 * A ConcreteHandler that delegates the request without trying to  
 * understand it at all. It may be easier to use in the user interface  
 * because it can specialize itself by defining methods that generates  
 * html, or by addressing similar user interface concerns.  
 * Some Clients see this object only as an instance of KeyValueStore  
 * and do not care how it satisfy their requests, while other ones  
 * may use it in its entirety (similar to a class-based adapter).  
 * No client knows that a chain of Handlers exists.  
 */ 
class FrontEnd extends AbstractKeyValueStore  
{  
    public function __construct(KeyValueStore $nextHandler)  
    {  
 $this->_nextHandler = $nextHandler;  
    }  
    public function getEscaped($key)  
    {  
 return htmlentities($this->get($key), ENT_NOQUOTES, 'UTF-8');  
    }  
}  
// Client code  
$store = new SlowStore(array('pd' => 'Philip K. Dick',  
 'ia' => 'Isaac Asimov',  
 'ac' => 'Arthur C. Clarke',  
 'hh' => 'Helmut Heißenbüttel'));  
// in development, we skip cache and pass $store directly to FrontEnd  
$cache = new InMemoryKeyValueStore($store);  
$frontEnd = new FrontEnd($cache);  
echo $frontEnd->get('ia'), "\n";  
echo $frontEnd->getEscaped('hh'), "\n";

关于PHP责任链设计模式的一些实现说明:
◆责任链可能已经存在于对象图中,和复合模式的例子一样;
◆此外,Handler抽象可能存在,也可能不存在,最好的选择是一个分开的Handler接口只可以执行handleRequest()操作,不要强制一个链只在一个层次中,因为后面的已经存在了;
◆也可能引入一个抽象类,但由于请求处理是一个正交关注,因此具体的类可能已经继承了其它类;
◆通过constructor 或setter,Handler(或下一个Handler)被注入到Client或前一个Handler;
◆请求对象通常是一个ValueObject,也可能被实现为一个Flyweight,在PHP中,它可能是一个标量类型,如string,注意在某些语言中,一个string就是一个不变的ValueObject。

简单的总结责任链模式,可以归纳为:用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。

PHP 相关文章推荐
如何写php程序?
Dec 08 PHP
PHP $_FILES函数详解
Mar 09 PHP
PHP错误抑制符(@)导致引用传参失败Bug的分析
May 02 PHP
VB中的RasEnumConnections函数返回632错误解决方法
Jul 29 PHP
php中实现记住密码下次自动登录的例子
Nov 06 PHP
curl和libcurl的区别简介
Jul 01 PHP
Thinkphp模板标签if和eq的区别和比较实例分析
Jul 01 PHP
php无限分类使用concat如何实现
Nov 05 PHP
PHP的全局错误处理详解
Apr 25 PHP
PHP书写格式详解(必看)
May 23 PHP
PHP快速排序quicksort实例详解
Sep 28 PHP
PHP设计模式之委托模式定义与用法简单示例
Aug 13 PHP
PHP设计模式之结构模式的深入解析
Jun 13 #PHP
PHP设计模式之命令模式的深入解析
Jun 13 #PHP
深入Memcache的Session数据的多服务器共享详解
Jun 13 #PHP
探讨:如何使用PHP实现计算两个日期间隔的年、月、周、日数
Jun 13 #PHP
判断php数组是否为索引数组的实现方法
Jun 13 #PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
Jun 13 #PHP
PHP 基于Yii框架中使用smarty模板的方法详解
Jun 13 #PHP
You might like
PHP面向对象概念
2011/11/06 PHP
浅析php插件 HTMLPurifier HTML解析器
2013/07/01 PHP
laravel 实现用户登录注销并限制功能
2019/10/24 PHP
jQuery 浮动广告实现代码
2008/12/25 Javascript
jQuery 自定义函数写法分享
2012/03/30 Javascript
JSP中使用JavaScript动态插入删除输入框实现代码
2014/06/13 Javascript
js获取UserControl内容为拼html时提供方便
2014/11/02 Javascript
Javascript的闭包详解
2014/12/26 Javascript
jQuery 中的 DOM 操作
2016/04/26 Javascript
JavaScript实现简单的拖动效果
2016/07/02 Javascript
jquery设置css样式的多种方法(总结)
2017/02/21 Javascript
SpringMVC简单整合Angular2的示例
2017/07/31 Javascript
浅谈AngularJS中使用$resource(已更新)
2017/09/14 Javascript
JavaScript实现的斑马线表格效果【隔行变色】
2017/09/18 Javascript
Emberjs 通过 axios 下载文件的方法
2019/09/03 Javascript
微信小程序页面渲染实现方法
2019/11/06 Javascript
vue中注册自定义的全局js方法
2019/11/15 Javascript
vue项目打包之开发环境和部署环境的实现
2020/04/23 Javascript
[02:25]DOTA2英雄基础教程 熊战士
2014/01/03 DOTA
Django中实现一个高性能计数器(Counter)实例
2014/07/09 Python
让Python代码更快运行的5种方法
2015/06/21 Python
Python 制作糗事百科爬虫实例
2016/09/22 Python
python的文件操作方法汇总
2017/11/10 Python
美国顶级奢侈茶:Mighty Leaf Tea(美泰茶)
2016/11/26 全球购物
skyn ICELAND官网:冰岛成分天然护肤品
2020/08/24 全球购物
TecoBuy澳大利亚:在线电子和小工具商店
2020/06/25 全球购物
教师自我鉴定范文
2013/11/10 职场文书
工程质量承诺书
2014/03/27 职场文书
青年文明号服务承诺
2014/03/31 职场文书
幼儿园大班开学寄语
2014/08/02 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
学校勤俭节约倡议书
2015/04/29 职场文书
2015年依法治校工作总结
2015/07/27 职场文书
教师读书活动心得体会
2016/01/14 职场文书
《我的伯父鲁迅先生》教学反思
2016/02/16 职场文书
学习计划是什么
2019/04/30 职场文书