PHP設計模式之責任鏈模式

PHP設計模式之責任鏈模式

責任鏈模式,屬於對象行爲型的設計模式。php

Gof類圖及解釋

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

短信發送類圖

短信過濾責任鏈模式版

完整源碼:github.com/zhangyue050…

// 詞彙過濾鏈條
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的中間件,有興趣的朋友翻翻源碼,典型的責任鏈模式的應用哦

下期看點

責任鏈貌似真的是很是高大上的一個設計模式,真的在目前不少的框架或系統中都有成熟的應用,若是不瞭解這個模式,可能在閱讀或者理解某些框架系統知識時就會茫然無措。下回,咱們來看看另外一個耳熟能詳的模式,它叫作代理模式

相關文章
相關標籤/搜索