设计模式:责任链模式

缘由

设计模式:责任链模式
说实话,责任链模式确实是我在学习设计模式中最简单的一个。思路非常简单。 head first 设计模式在附录中只用了两页,却让我懂了大概的原理。
首先说一下定义:
  • 责任链模式:chain of responsibility pattern 当你想让一个以上的对象有机会处理某个请求的时候,就使用责任链模式。

我的理解

就是有一个事务需要被处理,可能是由这个对象处理,也可能是由另一个对象处理。当然也可以有第三个对象处理。那么在责任链模式中,我们把能够处理的对象串成一个链,也就是类似于一个链表(但是链表只能从头开始遍历,而责任链模式可以从中间的某个对象开始),那么将需要处理的事务发给第一个对象,第一个对象看看能否处理,如果不能则传送给第二个处理对象...依次进行。
接着让我们看几个例子。

书中的不完美的例子

虽然最开始由这个例子而懂,然而这个例子确实是不太合理的。考虑背景如下:
某游戏公司的某个每日收到很多邮件,邮件种类如下:
  1. 来自fans:表示对公司的喜爱之情
  2. 来自父母:表示对该公司的游戏影响了孩子的学习,抱怨类的。
  3. 来自其它公司:表示想和该游戏公司合作
  4. 来自广告:属于垃圾邮件
那么该公司对这四类邮件的处理方式是不同的:
  1. 来自fans:给CEO
  2. 来自父母:给法律部门(中国人看来挺夸张的)
  3. 来自其他公司:业务部门
  4. 来自广告:删除
那么使用责任链模式就是使用如下一个类,Handler,其有一个成员变量,指向下一个Handler的实例对象,当然还有一个方法,用于处理邮件,图1,如下所示:



我们可以看到Handler这个抽象类,有4个实现类。当来一个邮件后,我们就将将给处理垃圾邮件的实现类,如果是垃圾邮件,那么我们就处理掉,如果不是垃圾邮件,就交下一个处理的实现类。依次类推。如下图所示:

原理大概如此,也有如下优点和缺点:

不合理之处

也许是我学的太浅,我想要是我要处理这个逻辑的话,为什么不用一个swithc语句呢?如果已经明确了这封邮件就是来自fans,直接传给FanHadnler就完了呗。何苦先传给SpamHandler?
然而,我这里不是想否认责任链模式,我主要是说这个例子举得不好。我觉得下一个公司请假的例子举得更合理一下。

请假的例子

试想,在公司要请假,首先肯定是给自己的直属领导,比如就是项目经理,如果项目经理批了那就算请到了。但是请假的天数太长,项目经理发现自己决定不了,就想去问问自己的直属领导,就叫项目总监吧,项目总监发现在自己的权限范围以内,可以批也就批了。但是还是处理不了呢?那么就得又叫给自己的直属领导,就当是:总经理吧。总经理一般是最大的了,总经理决定批了,那假也就准了,如果不批,这事也算完了。
Ok,这里关键就是,请假人,他只需要知道自己要请假,找项目经理就可以了,不用管项目经理具体会怎么做。而最后请假人得到的消息必然是:准假或者不准假。但是这个准假可能来自项目经理、项目总监、总经理。都有可能。但是请假人并不需要知道这些细节。责任链如下图4所示:

试想有遇到了这样的情况,公司的管理发生了改变,如果项目经理决定不了的请假的事宜,比如大于1天,需要交给人事部门,人事部门决定无法决定的再交给项目总监。那么我只需要把项目经理的后继者该懂以下即可,如下图所示5:


那么类图,我觉得下面这幅图7更好,来自:

可以看到,多了一个2个方法,那就是获得和设置后继处理者。

实现代码

貌似这个例子比较无聊,但是想了想再无限的做扩展也没什么意思。大概意思弄清楚就行了。

public abstract class Handler {
	
	private Handler successor;
	
	public Handler getSuccessor() {
		return successor;
	}


	public void setSuccessor(Handler successor) {
		this.successor = successor;
	}


	public abstract String vacationHanler(int day);
}






public class PMhandler extends Handler {


	@Override
	public String vacationHanler(int day) {
		if(day<1){
			return "PM:准假";
		}else{
			if(getSuccessor()==null){
				return "PM:不准假";
			}
			return getSuccessor().vacationHanler(day);
		}
	}
}




/**
 * PD:project director
 * @author chouyou
 *
 */
public class PDhandler extends Handler {


	@Override
	public String vacationHanler(int day) {
		if(day<7){
			return "PD:准假";
		}else{
			if(getSuccessor()==null){
				return "PD:不准假";
			}
			return getSuccessor().vacationHanler(day);
			
			
		}




	}
}




/**
 * TM:Tom Manager
 * @author chouyou
 *
 */
public class TMhandler extends Handler {


	@Override
	public String vacationHanler(int day) {
		if(day<30){
			return "TM:准假";
		}else{
			if(getSuccessor()==null){
				return "TM:不准假";
			}
			return getSuccessor().vacationHanler(day);
		}


	}


}






public class testMain {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Handler pMHandler=new PMhandler();
		Handler pDHandler=new PDhandler();
		Handler tMHandler=new TMhandler();
		
		pMHandler.setSuccessor(pDHandler);//在这里可以随意改变
		pDHandler.setSuccessor(tMHandler);
		
		int day=3;//请假天数。
		String reply=pMHandler.vacationHanler(day);//向项目经理申请
		System.out.println("请假"+day+"天,获得的答复是:"+reply);
	}


}

运行结果:
请假3天,获得的答复是:PD:准假
请假33天,获得的答复是:TM:不准假

总结

这玩意,要是能在项目中信手拈来那才是真本事,懂了点含义觉得并不牛逼。
这篇博客里写到了Tomcat中如何使用这个责任链模式,有空可以看看


源代码

很简单的代码,就不打包上传了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值