1. 程式人生 > >職責鏈模式——大公司病

職責鏈模式——大公司病

在體制內,我們辦理什麼業務或者提出什麼方案,大多數情況下都需要走一定的審批流程,大到以一家公司的方案審批流程,小到在想向學校提出請假請求,這中間我們的請求都有可能被流程中那個的某一環節得到處理。由於筆者對向學校請假的千辛萬苦記憶深刻,現在就以向學校請假為例子來演示一下職責鏈的使用。

假設現在請假一天內只需要向任課老師請假,請假1~3天的向學院輔導員請假,請假大於三天的要向學院領導請假。在這個模型中,我們的請求會依次向上級領導傳遞,直到請求達到的單位具有處理該請求的權利。

首先先來定義我們的請假類(也就是請求):

class request{
  //請假天數
  public $days
; public function __construct($num){ $this->days=$num; } public function setDays($num){ $this->days=$num; } }

接下來定義各級單位(也就是處於職責鏈上處理請求的物件).
定義抽象處理者:

abstract class handler{
     protected $successor;
     public function __construct($successor){
       $this->successor=$successor
; } public function setSuccessor(handler $successor){ $this->successor=$successor; } abstact function handle(request $request); }

定義具體處理者:

class teacher extends handler{
    public $name='任課老師';
    function handle(request $request){
      if($request->days <1
){ echo "$this->name:批准{$request->days}天假期<br>"; }else{ $this->successor->handle($request); } } } class counsellor extends handler{ public $name='輔導員'; function handle(request $request){ if($request->days<=3){ echo "$this->name:批准{$request->days}天假期<br>"; }else{ $this->successor->handle($request); } } } class leader extends handler{ public $name='學院領導'; function handle(request $request){ if($request->days <7){ echo "$this->name:批准{$request->days}天假期<br>"; }else{ echo "請假這麼多天,你自己看著辦<br>"; //$this->successor->handle($request); } } }

接下來我們就可以通過在客戶端中設定處理者的下一級處理者,從而構成職責鏈,是的,我們可以靈活的調整職責鏈上各個物件的位置順序和調整整個職責鏈的長度。

//先構造好職責鏈
$leader=new leader(null);
$counsellor=new counsellor($leader);
$teacher=new teacher($counsellor);
//例項化一個請求後傳遞請求給位於第一個節點的處理者
$request=new request(0.5);
$teacher->handle($request);
echo "<hr>";
$request->setDays(2);
$teacher->handle($request);
echo "<hr>";
$request->setDays(5);
$teacher->handle($request);
echo "<hr>";
$request->setDays(10);
$teacher->handle($request);
echo "<hr>";

執行結果:
這裡寫圖片描述

總結
當需要根據請求的某個屬性值將請求分發給許可權不同的處理物件時候,可以採用職責鏈模式,將這些處理物件按照一定的順序串聯起來,使得每個物件都有機會處理請求,如果處理不了則將請求傳遞到下一個處理物件,直到有物件來處理這個請求,要避免請求分發到職責鏈的最後仍得不到處理的情況。