責任鏈模式,屬于物件行為型的設計模式,
Gof類圖及解釋
GoF定義:使多個物件都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系,將這些物件連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個物件處理它為止,
GoF類圖

代碼實作
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 '請求引數是數字:' . $request;
} else {
return $this->successor->HandleRequst($request);
}
}
}
class ConcreteHandler2 extends Handler
{
public function HandleRequst($request)
{
if (is_string($request)) {
return '請求引數是字串:' . $request;
} else {
return $this->successor->HandleRequst($request);
}
}
}
class ConcreteHandler3 extends Handler
{
public function HandleRequst($request)
{
return '我也不知道請求引數是啥了,你猜猜?' . gettype($request);
}
}
三個責任鏈條的具體實作,主要功能是判斷傳入的資料型別,如果是數字由第一個類處理,如果是字串,則第二個類處理,如果是其他型別,第三個類統一處理,
$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;
}
客戶端的呼叫,依次實體化三個責任鏈實體,并指定鏈條成員,創建請求引數,之后通過責任鏈來進行結果判斷,
- 責任鏈非常適合的一種場景,就是對請求引數進行逐層過濾,就像我們作業時使用釘釘之類的辦公軟體,當需要提加班或者休假申請時,那一層層的審批流程就是對這個模式最完美的解釋
- 我們可以攔截請求,直接回傳,也可以對請求內容進行完善修改交給下一個類來進行處理,但至少有一個類是要回傳結果的,
- 請求不一定都會被處理,也有可能完全不處理就回傳或者傳遞給下一個處理類來進行處理
我們一直在說手機制造這個行業,之前我們一直是交給代工廠來進行手機的組裝生產,這回,我們自己建立了一條流水線,而這個流水線,就非常像責任鏈模式,怎么說呢,從一臺手機的裝配說起,有操作員將手機主板(初始請求)放到流水線上,然后工人開始添加記憶體、CPU、攝像頭(各種責任鏈條類進行處理),期間也會經過測驗和調整以達到最佳出廠性能,最后拼裝成一臺完整的手機交到客戶的手中,這種作業流是不是和責任鏈非常相似呢!!
完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain.php
實體
依然還是短信功能,但這次我們要實作的是一個短信內容過濾的子功能,大家都知道,我們對廣告有著嚴格的規定,許多詞都在廣告法中被標記為禁止使用的詞匯,更有些嚴重的詞匯可能會引來不必要的麻煩,這時候,我們就需要一套過濾機制來進行詞匯的過濾,針對不同型別的詞匯,我們可以通過責任鏈來進行過濾,比如嚴重違法的詞匯當然是這條資訊都不能通過,一些比較嚴重但可以繞過的詞,我們可以進行替換或者加星處理,這樣,客戶端不需要一大堆的if..else..來進行邏輯判斷,使用責任鏈讓他們一步步的進行審批就好啦!!
短信發送類圖

完整原始碼: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 = "現在開始測驗鏈條1:陳述句中不包含敏感詞,需要替換掉打架這種詞,然后給手機號加上星:13333333333,這樣的資料才可以對外展示哦";
echo $f1->filter($m1);
echo PHP_EOL;
$m2 = "現在開始測驗鏈條2:這條陳述句走不到后面,因為包含了毒X,直接就報錯了!!!陳述句中不包含敏感詞,需要替換掉打架這種詞,然后給手機號加上星:13333333333,這樣的資料才可以對外展示哦";
echo $f1->filter($m2);
echo PHP_EOL;
說明
- 在這個例子中,我們對訊息內容進行了各種處理,當有新的需求產生時,我們只需要加入新的過濾類,然后調整客戶端的執行順序即可
- 使用了next來標識下一步的操作,使用過Laravel的同學一定馬上聯想到了中間件,當然,用過Node開發服務器的同學更是不會陌生,早就對這個設計模式了如指掌了,
- 責任鏈的運用真的非常廣泛,在各種作業流軟體及中間件組件中都可以看到,同時配合Linux下的管道思想,可以把這個模式的優勢發揮到極致
- Laravel的中間件,有興趣的朋友翻翻原始碼,典型的責任鏈模式的應用哦
下期看點
責任鏈貌似真的是非常高大上的一個設計模式,真的在目前很多的框架或系統中都有成熟的應用,如果不了解這個模式,可能在閱讀或者理解某些框架系統知識時就會茫然無措,下回,我們來看看另一個耳熟能詳的模式,它叫做代理模式,
關注公眾號:【硬核專案經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、專案管理學習資料
知乎、公眾號、抖音、頭條搜索【硬核專案經理】
B站ID:482780532
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/238668.html
標籤:其他
