责任链模式,属于对象行为型的设计模式。

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的中间件,有趣味的敌人翻翻源码,典型的责任链模式的利用哦

下期看点

责任链貌似真的是十分高大上的一个设计模式,真的在目前很多的框架或零碎中都有成熟的利用,如果不理解这个模式,可能在浏览或者了解某些框架零碎常识时就会茫然无措。下回,咱们来看看另一个耳熟能详的模式,它叫做代理模式

各自媒体平台均可搜寻【硬核项目经理】