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 相关文章推荐
Windows IIS PHP 5.2 安装与配置方法
Jun 08 PHP
php 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
Jun 03 PHP
php visitFile()遍历指定文件夹函数
Aug 21 PHP
php INI配置文件的解析实现分析
Jan 04 PHP
php中神奇的fastcgi_finish_request
May 02 PHP
php中将数组存到文件里的实现代码
Jan 19 PHP
PHP flush()与ob_flush()的区别详解
Jun 03 PHP
使用openssl实现rsa非对称加密算法示例
Jan 24 PHP
PHP使用适合阅读的格式显示文件大小的方法
Mar 05 PHP
PHPStrom中实用的功能和快捷键大全
Sep 23 PHP
支持汉转拼和拼音分词的PHP中文工具类ChineseUtil
Feb 23 PHP
PHP CURL中传递cookie的方法步骤
May 09 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中DOMDocument简单用法示例代码(XML创建、添加、删除、修改)
2010/12/19 PHP
比较好用的PHP防注入漏洞过滤函数代码
2012/04/11 PHP
PHP中使用Imagick实现各种图片效果实例
2015/01/21 PHP
Yii2中添加全局函数的方法分析
2017/05/04 PHP
PHP ElasticSearch做搜索实例讲解
2020/02/05 PHP
Javascript异步表单提交,图片上传,兼容异步模拟ajax技术
2010/05/10 Javascript
仅IE支持clearAttributes/mergeAttributes方法使用介绍
2012/05/04 Javascript
THREE.JS入门教程(5)你应当知道的十件事
2013/01/24 Javascript
javaScript arguments 对象使用介绍
2013/10/18 Javascript
JS、DOM和JQuery之间的关系示例分析
2014/04/09 Javascript
jQuery实现长按按钮触发事件的方法
2015/02/02 Javascript
用户代理字符串userAgent可实现的四个识别
2015/09/20 Javascript
jQuery 如何实现一个滑动按钮开关
2016/12/01 Javascript
如何解决hover在ie6中的兼容性问题
2016/12/15 Javascript
原生js实现移动端触摸轮播的示例代码
2017/12/22 Javascript
React Router v4 入坑指南(小结)
2018/04/08 Javascript
Flutter部件内部状态管理小结之实现Vue的v-model功能
2019/06/11 Javascript
详解webpack打包vue项目之后生成的dist文件该怎么启动运行
2019/09/06 Javascript
[05:37]DOTA2-DPC中国联赛 正赛 Elephant vs iG 选手采访
2021/03/11 DOTA
Python的高级Git库 Gittle
2014/09/22 Python
用Python实现数据的透视表的方法
2018/11/16 Python
使用python对文件中的单词进行提取的方法示例
2018/12/21 Python
Python实现12306火车票抢票系统
2019/07/04 Python
Python操作列表常用方法实例小结【创建、遍历、统计、切片等】
2019/10/25 Python
Python 实现键盘鼠标按键模拟
2020/11/18 Python
发现两个有趣的CSS3动画效果
2013/08/14 HTML / CSS
HTML5 本地存储实现购物车功能
2017/09/07 HTML / CSS
shallow copy和deep copy的区别
2016/05/09 面试题
高中生学习的自我评价
2013/12/14 职场文书
给酒店员工的表扬信
2014/01/11 职场文书
政法学院毕业生求职信
2014/02/28 职场文书
渠道运营商合作协议书范本
2014/10/06 职场文书
教师个人自我评价
2015/03/04 职场文书
十八大观后感
2015/06/12 职场文书
如何使用Python实现一个简易的ORM模型
2021/05/12 Python
详解Python如何批量采集京东商品数据流程
2022/01/22 Python