您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“PHP中的責(zé)任鏈模式是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
責(zé)任鏈模式,屬于對(duì)象行為型的設(shè)計(jì)模式。
GoF定義:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。
GoF類圖:
代碼實(shí)現(xiàn)
abstract class Handler { protected $successor; public function setSuccessor($successor) { $this->successor = $successor; } abstract public function HandleRequst($request); }
定義抽象責(zé)任鏈類,使用$successor保存后繼鏈條。
class ConcreteHandler1 extends Handler { public function HandleRequst($request) { if (is_numeric($request)) { return '請(qǐng)求參數(shù)是數(shù)字:' . $request; } else { return $this->successor->HandleRequst($request); } } } class ConcreteHandler2 extends Handler { public function HandleRequst($request) { if (is_string($request)) { return '請(qǐng)求參數(shù)是字符串:' . $request; } else { return $this->successor->HandleRequst($request); } } } class ConcreteHandler3 extends Handler { public function HandleRequst($request) { return '我也不知道請(qǐng)求參數(shù)是啥了,你猜猜?' . gettype($request); } }
三個(gè)責(zé)任鏈條的具體實(shí)現(xiàn),主要功能是判斷傳入的數(shù)據(jù)類型,如果是數(shù)字由第一個(gè)類處理,如果是字符串,則第二個(gè)類處理。如果是其他類型,第三個(gè)類統(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)用,依次實(shí)例化三個(gè)責(zé)任鏈實(shí)例,并指定鏈條成員。創(chuàng)建請(qǐng)求參數(shù),之后通過(guò)責(zé)任鏈來(lái)進(jìn)行結(jié)果判斷。
責(zé)任鏈非常適合的一種場(chǎng)景,就是對(duì)請(qǐng)求參數(shù)進(jìn)行逐層過(guò)濾,就像我們工作時(shí)使用釘釘之類的辦公軟件。當(dāng)需要提加班或者休假申請(qǐng)時(shí),那一層層的審批流程就是對(duì)這個(gè)模式最完美的解釋
我們可以攔截請(qǐng)求,直接返回,也可以對(duì)請(qǐng)求內(nèi)容進(jìn)行完善修改交給下一個(gè)類來(lái)進(jìn)行處理,但至少有一個(gè)類是要返回結(jié)果的。
請(qǐng)求不一定都會(huì)被處理,也有可能完全不處理就返回或者傳遞給下一個(gè)處理類來(lái)進(jìn)行處理
我們一直在說(shuō)手機(jī)制造這個(gè)行業(yè),之前我們一直是交給代工廠來(lái)進(jìn)行手機(jī)的組裝生產(chǎn),這回,我們自己建立了一條流水線。而這個(gè)流水線,就非常像責(zé)任鏈模式,怎么說(shuō)呢,從一臺(tái)手機(jī)的裝配說(shuō)起。有操作員將手機(jī)主板(初始請(qǐng)求)放到流水線上,然后工人開(kāi)始添加內(nèi)存、CPU、攝像頭(各種責(zé)任鏈條類進(jìn)行處理),期間也會(huì)經(jīng)過(guò)測(cè)試和調(diào)整以達(dá)到最佳出廠性能。最后拼裝成一臺(tái)完整的手機(jī)交到客戶的手中,這種工作流是不是和責(zé)任鏈非常相似呢!!
完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain.php
依然還是短信功能,但這次我們要實(shí)現(xiàn)的是一個(gè)短信內(nèi)容過(guò)濾的子功能。大家都知道,我們對(duì)廣告有著嚴(yán)格的規(guī)定,許多詞都在廣告法中被標(biāo)記為禁止使用的詞匯,更有些嚴(yán)重的詞匯可能會(huì)引來(lái)不必要的麻煩。這時(shí)候,我們就需要一套過(guò)濾機(jī)制來(lái)進(jìn)行詞匯的過(guò)濾。針對(duì)不同類型的詞匯,我們可以通過(guò)責(zé)任鏈來(lái)進(jìn)行過(guò)濾,比如嚴(yán)重違法的詞匯當(dāng)然是這條信息都不能通過(guò)。一些比較嚴(yán)重但可以繞過(guò)的詞,我們可以進(jìn)行替換或者加星處理,這樣,客戶端不需要一大堆的if..else..來(lái)進(jìn)行邏輯判斷,使用責(zé)任鏈讓他們一步步的進(jìn)行審批就好啦?。?/p>
短信發(fā)送類圖
完整源碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/11.chain-of-responsiblity/source/chain-filter-message.php
// 詞匯過(guò)濾鏈條 abstract class FilterChain { protected $next; public function setNext($next) { $this->next = $next; } abstract public function filter($message); } // 嚴(yán)禁詞匯 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; } } } // 手機(jī)號(hào)加星 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)在開(kāi)始測(cè)試鏈條1:語(yǔ)句中不包含敏感詞,需要替換掉打架這種詞,然后給手機(jī)號(hào)加上星:13333333333,這樣的數(shù)據(jù)才可以對(duì)外展示哦"; echo $f1->filter($m1); echo PHP_EOL; $m2 = "現(xiàn)在開(kāi)始測(cè)試鏈條2:這條語(yǔ)句走不到后面,因?yàn)榘硕綳,直接就報(bào)錯(cuò)了!??!語(yǔ)句中不包含敏感詞,需要替換掉打架這種詞,然后給手機(jī)號(hào)加上星:13333333333,這樣的數(shù)據(jù)才可以對(duì)外展示哦"; echo $f1->filter($m2); echo PHP_EOL;
說(shuō)明
在這個(gè)例子中,我們對(duì)消息內(nèi)容進(jìn)行了各種處理。當(dāng)有新的需求產(chǎn)生時(shí),我們只需要加入新的過(guò)濾類,然后調(diào)整客戶端的執(zhí)行順序即可
使用了next來(lái)標(biāo)識(shí)下一步的操作,使用過(guò)Laravel的同學(xué)一定馬上聯(lián)想到了中間件。當(dāng)然,用過(guò)Node開(kāi)發(fā)服務(wù)器的同學(xué)更是不會(huì)陌生,早就對(duì)這個(gè)設(shè)計(jì)模式了如指掌了。
責(zé)任鏈的運(yùn)用真的非常廣泛,在各種工作流軟件及中間件組件中都可以看到,同時(shí)配合Linux下的管道思想,可以把這個(gè)模式的優(yōu)勢(shì)發(fā)揮到極致
Laravel的中間件,有興趣的朋友翻翻源碼,典型的責(zé)任鏈模式的應(yīng)用哦
“PHP中的責(zé)任鏈模式是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。