GoF类图
任务链模式
代码实现

abstractclassHandler{protected$successor;publicfunctionsetSuccessor($successor){$this->successor=$successor;}abstractpublicfunctionHandleRequst($request);}
定义抽象任务链类,利用$successor保存后继链条。
classConcreteHandler1extendsHandler{publicfunctionHandleRequst($request){if(is_numeric($request)){return'要求参数是数字:'.$request;}else{return$this->successor->HandleRequst($request);}}}classConcreteHandler2extendsHandler{publicfunctionHandleRequst($request){if(is_string($request)){return'要求参数是字符串:'.$request;}else{return$this->successor->HandleRequst($request);}}}classConcreteHandler3extendsHandler{publicfunctionHandleRequst($request){return'我也不知道要求参数是啥了,你猜猜?'.gettype($request);}}
三个任务链条的详细实现,紧张功能是判断传入的数据类型,如果是数字由第一个类处理,如果是字符串,则第二个类处理。如果是其他类型,第三个类统一处理。
$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
//词汇过滤链条abstractclassFilterChain{protected$next;publicfunctionsetNext($next){$this->next=$next;}abstractpublicfunctionfilter($message);}//严禁词汇classFilterStrictextendsFilterChain{publicfunctionfilter($message){foreach(['枪X','弹X','毒X']as$v){if(strpos($message,$v)!==false){thrownew\Exception('该信息包含敏感词汇!
');}}if($this->next){return$this->next->filter($message);}else{return$message;}}}//警告词汇classFilterWarningextendsFilterChain{publicfunctionfilter($message){$message=str_replace(['斗殴','丰胸','偷税'],'',$message);if($this->next){return$this->next->filter($message);}else{return$message;}}}//手机号加星classFilterMobileextendsFilterChain{publicfunctionfilter($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=newFilterStrict();$f2=newFilterWarning();$f3=newFilterMobile();$f1->setNext($f2);$f2->setNext($f3);$m1="现在开始测试链条1:语句中不包含敏感词,须要更换掉斗殴这种词,然后给手机号加上星:13333333333,这样的数据才可以对外展示哦";echo$f1->filter($m1);echoPHP_EOL;$m2="现在开始测试链条2:这条语句走不到后面,由于包含了毒X,直接就报错了!
!
!
语句中不包含敏感词,须要更换掉斗殴这种词,然后给手机号加上星:13333333333,这样的数据才可以对外展示哦";echo$f1->filter($m2);echoPHP_EOL;
解释
在这个例子中,我们对内容进行了各种处理。当有新的需求产生时,我们只须要加入新的过滤类,然后调度客户真个实行顺序即可利用了next来标识下一步的操作,利用过Laravel的同学一定立时遐想到了中间件。当然,用过Node开拓做事器的同学更是不会陌生,早就对这个设计模式管窥蠡测了。任务链的利用真的非常广泛,在各种事情流软件及中间件组件中都可以看到,同时合营Linux下的管道思想,可以把这个模式的上风发挥到极致Laravel的中间件,有兴趣的朋友翻翻源码,范例的任务链模式的运用哦下期看点任务链貌似真的是非常高大上的一个设计模式,真的在目前很多的框架或系统中都有成熟的运用,如果不理解这个模式,可能在阅读或者理解某些框架系统知识时就会茫然无措。下回,我们来看看另一个耳熟能详的模式,它叫做代理模式。