zoukankan      html  css  js  c++  java
  • PHP设计模式漫谈之责任链模式

    【51CTO独家特稿】在上期的《PHP设计模式漫谈》中,我们讲到了PHP的代理模式,本节我们将继续深入PHP设计模式,讲解的行为模式是责任链模式,其目的是组织一个对象链处理一个如方法调用的请求。

    当ConcreteHandler(具体的处理程序)不知道如何满足来自Client的请求时,或它的目的不是这个时,它会委派给链中的下一个Handler(处理程序)来处理。
    这个设计模式通常和复合模式一起使用,其中有些叶子或容器对象默认委派操作给它们的父对象。另一个例子是,本地化通常是使用责任链处理的,当德语翻译适配器没有为翻译关键词找到合适的结果时,就返回到英语适配器或干脆直接显示关键词本身。

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

    PHP设计模式中的责任链模式 
    PHP设计模式中的责任链模式

    参与者:

    ◆Client(客户端):向Handler(处理程序)提交一个请求;

    ◆Handler(处理程序)抽象:接收一个请求,以某种方式满足它;

    ◆ConcreteHandlers(具体的处理程序):接收一个请求,设法满足它,如果不成功就委派给下一个处理程序。

    下面的代码实现了一个最著名的责任链示例:多级缓存。

    1. /**  
    2.  * The Handler abstraction. Objects that want to be a part of the  
    3.  * ChainOfResponsibility must implement this interface directly or via  
    4.  * inheritance from an AbstractHandler.  
    5.  */ 
    6. interface KeyValueStore  
    7. {  
    8.     /**  
    9.      * Obtain a value.  
    10.      * @param string $key  
    11.      * @return mixed  
    12.      */ 
    13.     public function get($key);  
    14. }  
    15.  
    16. /**  
    17.  * Basic no-op implementation which ConcreteHandlers not interested in  
    18.  * caching or in interfering with the retrieval inherit from.  
    19.  */ 
    20. abstract class AbstractKeyValueStore implements KeyValueStore  
    21. {  
    22.     protected $_nextHandler;  
    23.  
    24.     public function get($key)  
    25.     {  
    26.         return $this->_nextHandler->get($key);  
    27.     }  
    28. }  
    29.  
    30. /**  
    31.  * Ideally the last ConcreteHandler in the chain. At least, if inserted in  
    32.  * a Chain it will be the last node to be called.  
    33.  */ 
    34. class SlowStore implements KeyValueStore  
    35. {  
    36.     /**  
    37.      * This could be a somewhat slow store: a database or a flat file.  
    38.      */ 
    39.     protected $_values;  
    40.  
    41.     public function __construct(array $values = array())  
    42.     {  
    43.         $this->_values = $values;  
    44.     }  
    45.  
    46.     public function get($key)  
    47.     {  
    48.         return $this->_values[$key];  
    49.     }  
    50. }  
    51.  
    52. /**  
    53.  * A ConcreteHandler that handles the request for a key by looking for it in  
    54.  * its own cache. Forwards to the next handler in case of cache miss.  
    55.  */ 
    56. class InMemoryKeyValueStore implements KeyValueStore  
    57. {  
    58.     protected $_nextHandler;  
    59.     protected $_cached = array();  
    60.  
    61.     public function __construct(KeyValueStore $nextHandler)  
    62.     {  
    63.         $this->_nextHandler = $nextHandler;  
    64.     }  
    65.  
    66.     protected function _load($key)  
    67.     {  
    68.         if (!isset($this->_cached[$key])) {  
    69.             $this->_cached[$key] = $this->_nextHandler->get($key);  
    70.         }  
    71.     }  
    72.  
    73.     public function get($key)  
    74.     {  
    75.         $this->_load($key);  
    76.         return $this->_cached[$key];  
    77.     }  
    78. }  
    79.  
    80. /**  
    81.  * A ConcreteHandler that delegates the request without trying to  
    82.  * understand it at all. It may be easier to use in the user interface  
    83.  * because it can specialize itself by defining methods that generates  
    84.  * html, or by addressing similar user interface concerns.  
    85.  * Some Clients see this object only as an instance of KeyValueStore  
    86.  * and do not care how it satisfy their requests, while other ones  
    87.  * may use it in its entirety (similar to a class-based adapter).  
    88.  * No client knows that a chain of Handlers exists.  
    89.  */ 
    90. class FrontEnd extends AbstractKeyValueStore  
    91. {  
    92.     public function __construct(KeyValueStore $nextHandler)  
    93.     {  
    94.         $this->_nextHandler = $nextHandler;  
    95.     }  
    96.  
    97.     public function getEscaped($key)  
    98.     {  
    99.         return htmlentities($this->get($key), ENT_NOQUOTES, 'UTF-8');  
    100.     }  
    101. }  
    102.  
    103. // Client code  
    104. $store = new SlowStore(array('pd' => 'Philip K. Dick',  
    105.                              'ia' => 'Isaac Asimov',  
    106.                              'ac' => 'Arthur C. Clarke',  
    107.                              'hh' => 'Helmut Heißenbüttel'));  
    108. // in development, we skip cache and pass $store directly to FrontEnd  
    109. $cache = new InMemoryKeyValueStore($store);  
    110. $frontEnd = new FrontEnd($cache);  
    111.  
    112. echo $frontEnd->get('ia'), "\n";  
    113. 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)一样传递下去。

    51CTO会在下周继续深入PHP设计模式,讲解PHP中的结构化模式摘要,敬请关注。

  • 相关阅读:
    服务控制器
    .Net Web项目安装包制作 (一)
    C#制作Windows service服务系列一:制作一个可安装、可启动、可停止、可卸载的Windows
    用Visual C#创建Windows服务程序
    插件的“动态替换”
    .Net Web项目安装包制作(三)补充说明
    .net打包/C#WinFrom程序打包
    C#制作Windows service服务系列三制作可控制界面的Windows服务(windows service)
    C#制作Windows service服务系列二演示一个定期执行的windows服务及调试
    .Net Web项目安装包制作 (二)数据库安装、其他组件的安装
  • 原文地址:https://www.cnblogs.com/rosesmall/p/2418479.html
Copyright © 2011-2022 走看看