責任鏈模式,屬於對象行爲型的設計模式。php
GoF定義:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。git
GoF類圖github
代碼實現設計模式
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、攝像頭(各類責任鏈條類進行處理),期間也會通過測試和調整以達到最佳出廠性能。最後拼裝成一臺完整的手機交到客戶的手中,這種工做流是否是和責任鏈很是類似呢!!測試
完整代碼:github.com/zhangyue050…this
依然仍是短信功能,但此次咱們要實現的是一個短信內容過濾的子功能。你們都知道,咱們對廣告有着嚴格的規定,許多詞都在廣告法中被標記爲禁止使用的詞彙,更有些嚴重的詞彙可能會引來沒必要要的麻煩。這時候,咱們就須要一套過濾機制來進行詞彙的過濾。針對不一樣類型的詞彙,咱們能夠經過責任鏈來進行過濾,好比嚴重違法的詞彙固然是這條信息都不能經過。一些比較嚴重但能夠繞過的詞,咱們能夠進行替換或者加星處理,這樣,客戶端不須要一大堆的if..else..來進行邏輯判斷,使用責任鏈讓他們一步步的進行審批就好啦!!spa
短信發送類圖
// 詞彙過濾鏈條
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;
複製代碼
說明
責任鏈貌似真的是很是高大上的一個設計模式,真的在目前不少的框架或系統中都有成熟的應用,若是不瞭解這個模式,可能在閱讀或者理解某些框架系統知識時就會茫然無措。下回,咱們來看看另外一個耳熟能詳的模式,它叫作代理模式。