当前位置:首页 > PHP教程 > php高级应用 > 列表

一文读懂php设计模式之责任链模式

发布: 来源: PHP粉丝网  添加日期:2022-07-22 14:32:49 浏览: 评论:0 

责任链模式属于行为型设计模式,将请求沿着处理者链进行发送, 收到请求后, 每个处理者均可对请求进行处理, 或将请求传递给链上的下个处理者,链上的每个处理者都有自己的处理职责,所以叫责任链模式。

场景

假如目前有一个系统,现在我们希望对系统的访问进行限制。首先是登录验证,该系统的所有请求都需要在登录状态下才能获取。

过了一段时间后,老板觉得应该加入防爬虫程序。老板的任务最大,你立即将防爬虫的功能加入到原本的校验代码中。目前就登录校验以及防爬虫校验,还不是很复杂。但又过了几天,老板又觉得应该加入限流的校验……。过了几天,老板……。

关于校验的代码块已经变的臃肿不堪,代码变得难以阅读、难以维护。这个时候,如果我们用责任链模式来重写校验的功能系统,那么就会像下面一样:

一文读懂php设计模式之责任链模式

通过责任链模式,多个处理者都有机会处理请求。将原本的模块分成多个处理者来处理,符合单一职责原则,代码的可读性也大大提高。另外,非常容易扩展,需要新的校验功能时,只要添加新的处理者即可,符合开闭原则。

责任链模式结构

下面我们来完成一个责任链模式结构的代码。每个处理者的功能非常简单,就是处理请求,然后设置下一个请求处理者。下面是示例代码:

  1. abstract class AHandler 
  2.  
  3. { 
  4.  
  5.     protected $nextHandler = null; 
  6.  
  7.       
  8.  
  9.     public function setNext (AHandler $handler) 
  10.  
  11.     { 
  12.  
  13.         $this->nextHandler = $handler; 
  14.  
  15.     } 
  16.  
  17.       
  18.  
  19.     abstract public function handler (); 
  20.  
  21. } 
  22.  
  23. class Handler1 extends AHandler 
  24.  
  25. { 
  26.  
  27.     public function handler() 
  28.  
  29.     { 
  30.  
  31.         $handled = false; 
  32.  
  33.           
  34.  
  35.         // 处理请求 
  36.  
  37.         echo 'Handler1接受到了请求' . PHP_EOL; 
  38.  
  39.           
  40.  
  41.         if (!$handled && $this->nextHandler) { 
  42.  
  43.             $this->nextHandler->handler(); 
  44.  
  45.         } 
  46.  
  47.     } 
  48.  
  49. } 
  50.  
  51. class Handler2 extends AHandler 
  52.  
  53. { 
  54.  
  55.     public function handler() 
  56.  
  57.     { 
  58.  
  59.         $handled = false; 
  60.  
  61.           
  62.  
  63.         // 处理请求 
  64.  
  65.         echo 'Handler2接受到了请求' . PHP_EOL; 
  66.  
  67.           
  68.  
  69.         if (!$handled && $this->nextHandler) { 
  70.  
  71.             $this->nextHandler->handler(); 
  72.  
  73.         } 
  74.  
  75.     } 
  76.  
  77. } 
  78.  
  79. class Handler3 extends AHandler 
  80.  
  81. { 
  82.  
  83.     public function handler() 
  84.  
  85.     { 
  86.  
  87.         $handled = false; 
  88.  
  89.           
  90.  
  91.         // 处理请求 
  92.  
  93.         echo 'Handler3接受到了请求' . PHP_EOL; 
  94.  
  95.           
  96.  
  97.         if (!$handled && $this->nextHandler) { 
  98.  
  99.             $this->nextHandler->handler(); 
  100.  
  101.         } 
  102.  
  103.     } 
  104.  
  105. } 

使用代码实例如下:

  1. $handler1 = new Handler1(); 
  2.  
  3. $handler2 = new Handler2(); 
  4.  
  5. $handler3 = new Handler3(); 
  6.  
  7. $handler1->setNext($handler2); 
  8.  
  9. $handler2->setNext($handler3); 
  10.  
  11. $handler1->handler(); 

上述代码虽然完成了责任链的结构,但还有一些问题,如果程序员对业务或责任链模式不太清楚的话,可能会忘记在handler方法里加入下面这段代码:

  1. if (!$handled && $this->nextHandler) { 
  2.  
  3.     $this->nextHandler->handler(); 
  4.  
  5. } 

那么就会造成责任链中断。另外,如果我们的处理者有10个或者更多,那么就要new出10个处理者,然后还要执行9次setNext。如果一不小心,写错了,就尴尬了。

现在,我们修改下上述的代码,修改后的代码如下:

  1. abstract class AHandler 
  2.  
  3. { 
  4.  
  5.     protected $nextHandler = null; 
  6.  
  7.       
  8.  
  9.     public function setNext (AHandler $handler) 
  10.  
  11.     { 
  12.  
  13.         $this->nextHandler = $handler; 
  14.  
  15.     } 
  16.  
  17.       
  18.  
  19.     // 使用了模板方法模式,防止程序员忘记写下段代码 
  20.  
  21.     public function handler () 
  22.  
  23.     { 
  24.  
  25.         if (!$this->doHandler() && $this->nextHandler) { 
  26.  
  27.             $this->nextHandler->handler(); 
  28.  
  29.         } 
  30.  
  31.     } 
  32.  
  33.       
  34.  
  35.     abstract public function doHandler (); 
  36.  
  37. } 
  38.  
  39.  
  40.  
  41. class Handler1 extends AHandler 
  42.  
  43. { 
  44.  
  45.     public function doHandler() 
  46.  
  47.     { 
  48.  
  49.         $handled = false; 
  50.  
  51.           
  52.  
  53.         // 处理请求 
  54.  
  55.         echo 'Handler1接受到了请求' . PHP_EOL; 
  56.  
  57.           
  58.  
  59.         return $handled; 
  60.  
  61.     } 
  62.  
  63. } 
  64.  
  65. class Handler2 extends AHandler 
  66.  
  67. { 
  68.  
  69.     public function doHandler() 
  70.  
  71.     { 
  72.  
  73.         $handled = false; 
  74.  
  75.           
  76.  
  77.         // 处理请求 
  78.  
  79.         echo 'Handler2接受到了请求' . PHP_EOL; 
  80.  
  81.           
  82.  
  83.         return $handled; 
  84.  
  85.     } 
  86.  
  87. } 
  88.  
  89.  
  90.  
  91. class Handler3 extends AHandler 
  92.  
  93. { 
  94.  
  95.     public function doHandler() 
  96.  
  97.     { 
  98.  
  99.         $handled = false; 
  100.  
  101.           
  102.  
  103.         // 处理请求 
  104.  
  105.         echo 'Handler3接受到了请求' . PHP_EOL; 
  106.  
  107.           
  108.  
  109.         return $handled; 
  110.  
  111.     } 
  112.  
  113. } 
  114.  
  115.  
  116.  
  117. class HandlerChain 
  118.  
  119. { 
  120.  
  121.     private $handlerChains = []; 
  122.  
  123.       
  124.  
  125.     public function __construct(array $handlerChains) 
  126.  
  127.     { 
  128.  
  129.         $this->handlerChains = $handlerChains; 
  130.  
  131.     } 
  132.  
  133.       
  134.  
  135.     public function addHandler (AHandler $handler) 
  136.  
  137.     { 
  138.  
  139.         $this->handlerChains[] = $handler; 
  140.  
  141.     } 
  142.  
  143.       
  144.  
  145.     public function handler () 
  146.  
  147.     { 
  148.  
  149.         $hdCnt = count($this->handlerChains); 
  150.  
  151.           
  152.  
  153.         for ($i = 0; $i < $hdCnt; $i ++) { 
  154.  
  155.             if (isset($this->handlerChains[$i])  
  156.  
  157.                   && isset($this->handlerChains[$i+1])) { 
  158.  
  159.                 $this->handlerChains[$i]->setNext($this->handlerChains[$i+1]); 
  160.  
  161.             } 
  162.  
  163.         } 
  164.  
  165.           
  166.  
  167.         $this->handlerChains[0]->handler(); 
  168.  
  169.     } 
  170.  
  171. } 

然后,使用代码如下:

  1. $handler1 = new Handler1(); 
  2.  
  3. $handler2 = new Handler2(); 
  4.  
  5. $handler3 = new Handler3(); 
  6.  
  7. $handerChian = new HandlerChain([$handler1, $handler2, $handler3]); 
  8.  
  9. $handerChian->handler(); 

更简单的实现方法

其实有一种更加简单的实现责任链模式的方法,代码如下:

  1. abstract class AHandler 
  2.  
  3. { 
  4.  
  5.     abstract public function handler (); 
  6.  
  7. } 
  8.  
  9.  
  10.  
  11. class Handler1 extends AHandler 
  12.  
  13. { 
  14.  
  15.     public function handler() 
  16.  
  17.     { 
  18.  
  19.         $handled = false; 
  20.  
  21.         // 处理请求 
  22.  
  23.         echo 'Handler1接受到了请求' . PHP_EOL; 
  24.  
  25.         return $handled; 
  26.  
  27.     } 
  28.  
  29. } 
  30.  
  31.  
  32.  
  33. // Handler2、Handler3代码省略 
  34.  
  35.  
  36.  
  37.  
  38.  
  39. class HandlerChain 
  40.  
  41. { 
  42.  
  43.     private $handlerChains = []; 
  44.  
  45.       
  46.  
  47.     public function __construct(array $handlerChains) 
  48.  
  49.     { 
  50.  
  51.         $this->handlerChains = $handlerChains; 
  52.  
  53.     } 
  54.  
  55.       
  56.  
  57.     public function addHandler (AHandler $handler) 
  58.  
  59.     { 
  60.  
  61.         $this->handlerChains[] = $handler; 
  62.  
  63.     } 
  64.  
  65.       
  66.  
  67.     public function handler () 
  68.  
  69.     { 
  70.  
  71.         foreach ($this->handlerChains as $handler) { 
  72.  
  73.             if ($handler->handler()) { 
  74.  
  75.                 break; 
  76.  
  77.             } 
  78.  
  79.         } 
  80.  
  81.     } 
  82.  
  83. } 

总结:

通过责任链模式,多个处理者都有机会处理请求。将原本的模块分成多个处理者来处理,符合单一职责原则,代码的可读性也大大提高。另外,非常容易扩展,需要新的功能时,只要添加新的处理者即可。

一般设计模式的定义是,处理者如果不能够处理该请求,就将请求传递给后一个处理者。其实,他也有一个变体,就是每个处理者都会处理请求。

Tags: php设计模式 php责任链模式

分享到: