PHP設計模式之責任鏈模式責任鏈模式,屬于對象行為型的設計模式,。 Gof類圖及解釋GoF定義:使多個對象都有機會處理請求,,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對象連成一條鏈,,并沿著這條鏈傳遞該請求,,直到有一個對象處理它為止。 GoF類圖
代碼實現(xiàn)
abstract class Handler { protected $successor; public function setSuccessor($successor) { $this->successor = $successor; } abstract public function HandleRequst($request); }
定義抽象責任鏈類,,使用$successor保存后繼鏈條,。 class ConcreteHandler1 extends Handler { public function HandleRequst($request) { if (is_numeric($request)) { return '請求參數(shù)是數(shù)字:' . $request; } else { return $this->successor->HandleRequst($request); } } }
class ConcreteHandler2 extends Handler { public function HandleRequst($request) { if (is_string($request)) { return '請求參數(shù)是字符串:' . $request; } else { return $this->successor->HandleRequst($request); } } }
class ConcreteHandler3 extends Handler { public function HandleRequst($request) { return '我也不知道請求參數(shù)是啥了,你猜猜,?' . gettype($request); } }
三個責任鏈條的具體實現(xiàn),,主要功能是判斷傳入的數(shù)據(jù)類型,如果是數(shù)字由第一個類處理,,如果是字符串,,則第二個類處理,。如果是其他類型,第三個類統(tǒng)一處理,。 $handle1 = new ConcreteHandler1(); $handle2 = new ConcreteHandler2(); $handle3 = new ConcreteHandler3();
$handle1->setSuccessor($handle2); $handle2->setSuccessor($handle3);
$requests = [22, 'aaa', 55, 'cc', [1, 2, 3], null, new stdClass];
foreach ($requests as $request) { echo $handle1->HandleRequst($request) . PHP_EOL; }
客戶端的調(diào)用,,依次實例化三個責任鏈實例,并指定鏈條成員,。創(chuàng)建請求參數(shù),,之后通過責任鏈來進行結(jié)果判斷。 責任鏈非常適合的一種場景,,就是對請求參數(shù)進行逐層過濾,,就像我們工作時使用釘釘之類的辦公軟件。當需要提加班或者休假申請時,,那一層層的審批流程就是對這個模式最完美的解釋 我們可以攔截請求,,直接返回,也可以對請求內(nèi)容進行完善修改交給下一個類來進行處理,,但至少有一個類是要返回結(jié)果的,。 請求不一定都會被處理,也有可能完全不處理就返回或者傳遞給下一個處理類來進行處理
我們一直在說手機制造這個行業(yè),,之前我們一直是交給代工廠來進行手機的組裝生產(chǎn),,這回,我們自己建立了一條流水線,。而這個流水線,,就非常像責任鏈模式,怎么說呢,,從一臺手機的裝配說起,。有操作員將手機主板(初始請求)放到流水線上,然后工人開始添加內(nèi)存,、CPU,、攝像頭(各種責任鏈條類進行處理),期間也會經(jīng)過測試和調(diào)整以達到最佳出廠性能,。最后拼裝成一臺完整的手機交到客戶的手中,,這種工作流是不是和責任鏈非常相似呢!,! 完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain.php 實例依然還是短信功能,,但這次我們要實現(xiàn)的是一個短信內(nèi)容過濾的子功能,。大家都知道,,我們對廣告有著嚴格的規(guī)定,許多詞都在廣告法中被標記為禁止使用的詞匯,,更有些嚴重的詞匯可能會引來不必要的麻煩,。這時候,,我們就需要一套過濾機制來進行詞匯的過濾。針對不同類型的詞匯,,我們可以通過責任鏈來進行過濾,,比如嚴重違法的詞匯當然是這條信息都不能通過。一些比較嚴重但可以繞過的詞,,我們可以進行替換或者加星處理,,這樣,客戶端不需要一大堆的if..else..來進行邏輯判斷,,使用責任鏈讓他們一步步的進行審批就好啦?。?/p> 短信發(fā)送類圖
完整源碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain-filter-message.php // 詞匯過濾鏈條 abstract class FilterChain { protected $next; public function setNext($next) { $this->next = $next; } abstract public function filter($message); }
// 嚴禁詞匯 class FilterStrict extends FilterChain { public function filter($message) { foreach (['槍X', '彈X', '毒X'] as $v) { if (strpos($message, $v) !== false) { throw new \Exception('該信息包含敏感詞匯,!'); } } if ($this->next) { return $this->next->filter($message); } else { return $message; } } }
// 警告詞匯 class FilterWarning extends FilterChain { public function filter($message) { $message = str_replace(['打架', '豐胸', '偷稅'], '*', $message); if ($this->next) { return $this->next->filter($message); } else { return $message; } } }
// 手機號加星 class FilterMobile extends FilterChain { public function filter($message) { $message = preg_replace("/(1[3|5|7|8]\d)\d{4}(\d{4})/i", "$1****$2", $message); if ($this->next) { return $this->next->filter($message); } else { return $message; } } }
$f1 = new FilterStrict(); $f2 = new FilterWarning(); $f3 = new FilterMobile();
$f1->setNext($f2); $f2->setNext($f3);
$m1 = "現(xiàn)在開始測試鏈條1:語句中不包含敏感詞,,需要替換掉打架這種詞,然后給手機號加上星:13333333333,,這樣的數(shù)據(jù)才可以對外展示哦"; echo $f1->filter($m1); echo PHP_EOL;
$m2 = "現(xiàn)在開始測試鏈條2:這條語句走不到后面,,因為包含了毒X,直接就報錯了?。,。≌Z句中不包含敏感詞,,需要替換掉打架這種詞,,然后給手機號加上星:13333333333,這樣的數(shù)據(jù)才可以對外展示哦"; echo $f1->filter($m2); echo PHP_EOL;
說明
在這個例子中,,我們對消息內(nèi)容進行了各種處理,。當有新的需求產(chǎn)生時,我們只需要加入新的過濾類,,然后調(diào)整客戶端的執(zhí)行順序即可 使用了next來標識下一步的操作,,使用過Laravel的同學一定馬上聯(lián)想到了中間件。當然,,用過Node開發(fā)服務器的同學更是不會陌生,,早就對這個設計模式了如指掌了。 責任鏈的運用真的非常廣泛,,在各種工作流軟件及中間件組件中都可以看到,,同時配合Linux下的管道思想,可以把這個模式的優(yōu)勢發(fā)揮到極致 Laravel的中間件,,有興趣的朋友翻翻源碼,,典型的責任鏈模式的應用哦
下期看點責任鏈貌似真的是非常高大上的一個設計模式,真的在目前很多的框架或系統(tǒng)中都有成熟的應用,,如果不了解這個模式,,可能在閱讀或者理解某些框架系統(tǒng)知識時就會茫然無措,。下回,我們來看看另一個耳熟能詳?shù)哪J?,它叫?em style="box-sizing: border-box;">代理模式,。
|