职责分明的责任链模式(Chain of Responsibility Pattern)
中国自古有重男轻女的观念,在古代,未婚女子要想出去逛街都要经过父亲的同意,而有丈夫的则要请示丈夫,如果丈夫去世了,有儿子的还得请示儿子,这就是所谓的“三从”。果然很苦逼!我们用程序来模拟一下这个过程:
<?php interface IWomen{ public function gettype(); public function getRequest(); } class Women implements IWomen{ /* * 1--未出嫁 * 2--出嫁 * 3--夫死 */ private $type = 0; private $request = ''; public function __construct( $type, $request ) { $this->type = $type; $this->request = $request; } public function gettype() { return $this->type; } public function getRequest() { return $this->request; } } interface IHandler{ public function handleMessage( $women ); } class Father implements IHandler{ public function handleMessage( $women ) { echo "女儿的请求是".$women->getRequest()."\n"; echo "父亲的答复是:同意!\n"; } } class Husband implements IHandler{ public function handleMessage( $women ) { echo "妻子的请求是".$women->getRequest()."\n"; echo "丈夫的答复是:同意!\n"; } } class Son implements IHandler{ public function handleMessage( $women ) { echo "母亲的请求是".$women->getRequest()."\n"; echo "儿子的答复是:同意!\n"; } } for($type = 1;$type<=3;$type++): $women = new Women($type,'逛街'); switch ($type) { case '1': $handler = new Father(); break; case '2': $handler = new Husband(); break; default: $handler = new Son(); break; } $handler->handleMessage($women); endfor; ?> 运行结果: 女儿的请求是逛街 父亲的答复是:同意! 妻子的请求是逛街 丈夫的答复是:同意! 母亲的请求是逛街 儿子的答复是:同意! [Finished in 0.1s]
实现很简单,代码也比较容易,但是这样的设计有几个问题:
1、职责界定不清晰
对女儿的提出的请示,应该在父亲类中做出决定,父亲有责任、有义务处理女儿的请求。因此Father类应该是知道女儿的请求自己处理,而不是在Client中进行组装出来,也就是说原本应该是父亲这个类做的事情抛给了其他地方进行处理。
2、代码臃肿
在client中写了swith判断条件,而且能随着能处理该类型的请示人员越多,switch判断就越多,这样倒置可读性大大下降。
3、耦合过重
client根据women的type来决定使用IHandler的哪个实现类来处理请求。但如果IHandler的实现类继续扩展呢,那就得修改client,与开闭原则违背了!
4、异常情况欠考虑
如果妻子是个不懂三从的人,她已有丈夫却向父亲去请示,那父亲应该如何处理?上面的程序完全没有考虑这种异常情况!
那该如何改进?不难发现,整个请示的过程可以构成一条“链”。“链头“是父亲,无论女子是否已结婚全都请示父亲,父亲得知女儿结婚了,就传给女儿的丈夫,丈夫如果过世了,再传给儿子。看下类图:
实现代码如下:
<?php interface IWomen{ public function gettype(); public function getRequest(); } class Women implements IWomen{ /* * 1--未出嫁 * 2--出嫁 * 3--夫死 */ private $type = 0; private $request = ''; public function __construct( $type, $request ) { $this->type = $type; $this->request = $request; } public function gettype() { return $this->type; } public function getRequest() { return $this->request; } } abstract class IHandler { const FATHER_LEVEL_REQUEST = 1; const HUSBAND_LEVEL_REQUEST = 2; const SON_LEVEL_REQUEST = 3; private $level = 0; private $nextHandler; protected function __construct( $level ) { $this->level = $level; } final public function handleMessage( $women ) { if ( $women->getType() == $this->level ) $this->reponse( $women );//这里回调子类方法 else { if ( $this->nextHandler != NULL ) $this->nextHandler->handleMessage( $women ); else echo "没地方请示了,按不同意处理!\n"; } } public function setNext( $handler ) { $this->nextHandler = $handler; } abstract protected function reponse( $women ); } class Father extends IHandler{ public function __construct() { parent::__construct( parent::FATHER_LEVEL_REQUEST ); } public function reponse( $women ) { echo "女儿的请求是".$women->getRequest()."\n"; echo "父亲的答复是:同意!\n"; } } class Husband extends IHandler{ public function __construct() { parent::__construct( parent::HUSBAND_LEVEL_REQUEST ); } public function reponse( $women ) { echo "妻子的请求是".$women->getRequest()."\n"; echo "丈夫的答复是:同意!\n"; } } class Son extends IHandler{ public function __construct() { parent::__construct( parent::SON_LEVEL_REQUEST ); } public function reponse( $women ) { echo "母亲的请求是".$women->getRequest()."\n"; echo "儿子的答复是:同意!\n"; } } for($i=0;$i<=3;$i++){ $women = new Women($i,'逛街'); $father = new Father(); $husband = new Husband(); $son = new Son(); $father->setNext($husband); $husband->setNext($son); $father->handleMessage($women); } ?> 运行结果: 没地方请示了,按不同意处理! 女儿的请求是逛街 父亲的答复是:同意! 妻子的请求是逛街 丈夫的答复是:同意! 母亲的请求是逛街 儿子的答复是:同意! [Finished in 0.1s]
例子中不难发现,其实还用到了模板方法模式。
责任链模式的定义
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式的优点
最为显著的优点就是将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦,提高系统的灵活性。
责任链模式的缺点
一是性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个问题。二是调试不是很方便,特别是链条比较长的,环节比较多的时候,由于采用了类似递归的方式 ,调试的时候逻辑可能比较复杂。
推荐阅读
-
php设计模式 Chain Of Responsibility (职责链模式)
-
责任链模式-Chain of Responsibility(Java实现), 例2
-
责任链模式-Chain of Responsibility(Java实现), 例1
-
责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)
-
java设计模式-Chain of Responsibility(责任者链)模式
-
设计模式之责任链模式(Chain of Responsibility )
-
responsibility php设计模式 Chain Of Responsibility 职责链模式
-
设计模式 - 责任链模式(Chain of Responsibility)--链式处理
-
php设计模式 Chain Of Responsibility (职责链模式)_PHP
-
职责链(Chain of Responsibility)模式