PHP设计模式的责任链模式,属于对象行为设计模式。Gof类图及解释GoF定义:让多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象链接成一个链,并沿着链传递请求,直到一个对象处理它。GoF类图代码实现abstractclassHandler{protected$successor;公共功能setSuccessor($successor){$this->successor=$successor;}abstractpublicfunctionHandleRequst($request);}定义了一个抽象责任链类,使用$successor保存后继链。classConcreteHandler1extendsHandler{publicfunctionHandleRequest($request){if(is_numeric($request)){return'请求参数是一个数字:'.$请求;}else{return$this->successor->HandleRequst($request);}}}classConcreteHandler2extendsHandler{publicfunctionHandleRequst($request){if(is_string($request)){return'请求参数是一个字符串:'.$请求;}else{return$this->successor->HandleRequst($request);}}}classConcreteHandler3extendsHandler{publicfunctionHandleRequst($request){return'我不知道请求参数是什么,你猜怎么着?'。获取类型($请求);}}三个责任链的具体实现,主要作用是判断传入的数据类型,如果是数字,由第一个类处理,如果是字符串,则由第二个类处理.如果是其他类型,则由第三类统一处理。$handle1=newConcreteHandler1();$handle2=newConcreteHandler2();$handle3=newConcreteHandler3();$handle1->setSuccessor($handle2);$handle2->setSuccessor($handle3);$requests=[22,'aaa',55,'cc',[1,2,3],null,newstdClass];foreach($requestsas$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//词汇过滤链抽象类FilterChain{protected$next;公共功能setNext($next){$this->next=$next;}abstractpublicfunctionfilter($message);}//词汇严禁classFilterStrictextendsFilterChain{publicfunctionfilter($message){foreach(['GunX','BombX','PoisonX']as$v){if(strpos($message,$v)!==false){thrownew\Exception('消息包含敏感词!');}}if($this->next){返回$this->next->filter($message);}else{返回$消息;}}}//警告词汇classFilterWarningextendsFilterChain{publicfunctionfilter($message){$message=str_replace(['打架','丰胸','逃税'],'*',$message);如果($this->next){return$this->next->filter($message);}else{返回$消息;}}}//电话号码星级类FilterMobileextendsFilterChain{publicfunctionfilter($message){$message=preg_replace("/(1[3|5|7|8]\d)\d{4}(\d{4})/i","$1****$2",$message);如果($this->next){return$this->next->filter($message);}else{返回$消息;}}}$f1=newFilterStrict();$f2=newFilterWarning();$f3=newFilterMobile();$f1->setNext($f2);$f2->setNext($f3);$m1="现在开始测试链1:句子中不包含敏感词,需要像fighting这样的词替换,然后给手机号加星号:13333333333,这样数据就可以公开展示了。";echo$f1->filter($m1);echoPHP_EOL;$m2="现在开始测试链2:这条语句无法到达后面,因为包含了毒X,直接报错!!!语句中不包含敏感词,需要将打字替换掉,然后在手机号码上加星标:13333333333,这样数据才能对外展示”;echo$f1->过滤器($m2);echoPHP_EOL;可见在这个例子中,我们对消息的内容进行了各种处理。当有新的需求出现时,我们只需要增加一个新的过滤类,然后调整客户端的执行顺序就可以使用next来标识下一个操作了。用过Laravel的同学肯定第一时间想到中间件。当然,用过Node开发服务器的同学都不会陌生,对这种设计模式早就耳熟能详了。责任链的应用实在是太广泛了。在各种工作流软件和中间件组件中都可以看到它的身影。同时,借助Linux下的流水线思想,可以将这种模式的优势发挥到极致。Laravel中间件,有兴趣的朋友看看源码,典型责任链模型的应用哦,下期看点责任链好像是一个很高大上的设计模式,确实有成熟的应用在许多当前的框架或系统中。如果不了解这种模式,在阅读或理解一些框架体系知识时可能会一头雾水。下一次,让我们来看看另一种熟悉的模式,它被称为代理模式。各媒体平台均可搜索【硬核项目经理】
