职责分明的责任链模式(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]

 例子中不难发现,其实还用到了模板方法模式

 

 

责任链模式的定义

使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

 

 

责任链模式的优点

最为显著的优点就是将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦,提高系统的灵活性。

 

 

责任链模式的缺点

一是性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个问题。二是调试不是很方便,特别是链条比较长的,环节比较多的时候,由于采用了类似递归的方式 ,调试的时候逻辑可能比较复杂。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值