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

所属分类: 网络编程 / PHP编程 阅读数: 1590
收藏 0 赞 0 分享
责任链模式,其目的是组织一个对象链处理一个如方法调用的请求。
当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实现的美国50个州选择列表实例

这篇文章主要介绍了php实现的美国50个州选择列表实例,可实现让当前州为选中状态的功能,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

PHP使用递归生成文章树

写递归函数,可考虑缓存,定义一些静态变量来存上一次运行的结果,多程序运行效率很有帮助.大概步骤如下:首先到数据库取数据,放到一个数组,然后把数据转化为一个树型状的数组,最后把这个树型状的数组转为html代码。下面我们来看个实例
收藏 0 赞 0 分享

wordpress安装过程中遇到中文乱码的处理方法

这篇文章主要介绍了wordpress安装过程中遇到中文乱码的处理方法,是个人项目中遇到的一个奇葩事件,经过一番研究,终于解决,这里记录下来分享给大家,有需要的小伙伴可以参考下。
收藏 0 赞 0 分享

php的crc32函数使用时需要注意的问题(不然就是坑)

这篇文章主要介绍了php的crc32函数使用时需要注意的问题(不然就是坑) ,需要的朋友可以参考下
收藏 0 赞 0 分享

PHP中把对象转换为关联数组代码分享

这篇文章主要介绍了PHP中把对象转换为关联数组代码分享,本文直接给出实现代码,需要的朋友可以参考下
收藏 0 赞 0 分享

php检测url是否存在的方法

这篇文章主要介绍了php检测url是否存在的方法,涉及php中get_headers及正则匹配的技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

php获取twitter最新消息的方法

这篇文章主要介绍了php获取twitter最新消息的方法,涉及php操作curl及正则替换的技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

php遍历CSV类实例

这篇文章主要介绍了php遍历CSV类,实例分析了php针对csv文件的打开、读取及遍历的技巧,非常具有实用价值,需要的朋友可以参考下
收藏 0 赞 0 分享

PHP使用mysqldump命令导出数据库

最近用php写一个数据备份的功能。做法是使用php的system函数执行mysqldump命令,进行备份,这里分享给大家,有需要的小伙伴可以参考下。
收藏 0 赞 0 分享

PHP用反撇号执行外部命令

shell_exec() 命令行实际上仅是反撇号 ` 操作符的变体,如果您编写过 shell 或 Perl 脚本,您就知道可以在反撇号操作符内部捕捉其他命令的输出。
收藏 0 赞 0 分享
查看更多