什么是职责链
职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
例子一:支付宝的花呗自动还款扣款顺序
余额->借记卡快捷->余额宝
首先会从余额扣款,若余额不足或扣款失败则将扣款这一动作往后传递~
例子二:备胎
母亲:闺女,你们也不小了。赶紧给我找个女婿,具体怎么找,你们自己决定。
大女儿:妈,别急,我正在找呢,我要求不高,对我好就行了。
小女儿:妈,我要求也不高,对我好也就可以啦~
女生说要求不高,往往要求很高~ 哼.jpg。但女生说自己懒,往往就是真的懒。这不,找上我这个程序员了。
大小女儿:foam,你是学计算机的,除了修电脑,帮忙找备胎也是会的哈~
foam:说吧,什么要求
大女儿:我要求不高,只要对我好就可以了。但,有钱很重要~
小女儿:我和姐姐一样,找个对我好的就行。但,长得帅很重要~
大小女儿:还有其他不是要求的要求嘛,长得高的不能太瘦,比较矮的又不能太胖;理科生的话最好会点音乐,文科生则需要懂点修电脑
foam:(转身吐血)你们还会改需求吗~
大小女儿:不会的
我知道,女生说不会,就是会!
于是我放弃了if…else的写法。
首先将备胎对象化是必须的。重要的是,给这些备胎串成一条链。每个节点,只要满足基本条件就返回给客户,否则往下传递,直到找到符合条件的备胎为止。
但,备胎的排序也是有条件的。大女儿说,最好有钱,那先将备胎们按身家排序,最有钱的排在链头,最穷的在链尾。小女儿的颜值要求也如法炮制。
用php简单实现的职责链demo
<?php abstract class Handler { private $successor = null; final public function append(Handler $handler) { if (is_null($this->successor)) { $this->successor = $handler; } else { $this->successor->append($handler); } } final public function handle() { $processed = $this->processing(); if (!$processed) { if (!is_null($this->successor)) { $processed = $this->successor->handle(); } } return $processed; } abstract protected function processing(); } class AHandler extends Handler { public function processing() { echo 'A processing '; if (满足要求) { return true; } return false; } } class BHandler extends Handler { public function processing() { echo 'B processing '; if (满足要求) { return true; } return false; } } class CHandler extends Handler { public function processing() { echo 'C processing '; if (满足要求) { return true; } return false; } } class Client { private $_chain; public function init() { //例子一(花呗扣款): $this->_chain = new AHandler(); $this->_chain->append(new BHandler); $this->_chain->append(new CHandler); //例子二(备胎): $hanlerList = getManOrderByRich(); $this->_chain = new $handlerList[0]; for ($i=1;$i<count($handlerList),++$i) { $this->_chain->append(new $handlerList[$i]); } } public function doIt() { $this->_chain->handle(); } } $client = new Client; $client->init(); $client->doIt();
对了,后来过了几天,大女儿来找我了。
大女儿:foam,我觉得钱不是最重要的,身高才是
foam:我知道了,你等我几分钟
……
于是我这么改了下代码
//$hanlerList = getManOrderByRich(); $hanlerList = getManOrderByTall(); $this->_chain = new $handlerList[0]; for ($i=1;$i<count($handlerList),++$i) { $this->_chain->append(new $handlerList[$i]); }
她说以后不会再来麻烦我了,我点了点头~我知道的~
几天后,果然如我知道的那般
hey,foam,在吗