缘由
设计模式:责任链模式
说实话,责任链模式确实是我在学习设计模式中最简单的一个。思路非常简单。 head first 设计模式在附录中只用了两页,却让我懂了大概的原理。
首先说一下定义:
接着让我们看几个例子。
某游戏公司的某个每日收到很多邮件,邮件种类如下:
我们可以看到Handler这个抽象类,有4个实现类。当来一个邮件后,我们就将将给处理垃圾邮件的实现类,如果是垃圾邮件,那么我们就处理掉,如果不是垃圾邮件,就交下一个处理的实现类。依次类推。如下图所示:
原理大概如此,也有如下优点和缺点:
然而,我这里不是想否认责任链模式,我主要是说这个例子举得不好。我觉得下一个公司请假的例子举得更合理一下。
Ok,这里关键就是,请假人,他只需要知道自己要请假,找项目经理就可以了,不用管项目经理具体会怎么做。而最后请假人得到的消息必然是:准假或者不准假。但是这个准假可能来自项目经理、项目总监、总经理。都有可能。但是请假人并不需要知道这些细节。责任链如下图4所示:
说实话,责任链模式确实是我在学习设计模式中最简单的一个。思路非常简单。 head first 设计模式在附录中只用了两页,却让我懂了大概的原理。
首先说一下定义:
- 责任链模式:chain of responsibility pattern 当你想让一个以上的对象有机会处理某个请求的时候,就使用责任链模式。
我的理解
就是有一个事务需要被处理,可能是由这个对象处理,也可能是由另一个对象处理。当然也可以有第三个对象处理。那么在责任链模式中,我们把能够处理的对象串成一个链,也就是类似于一个链表(但是链表只能从头开始遍历,而责任链模式可以从中间的某个对象开始),那么将需要处理的事务发给第一个对象,第一个对象看看能否处理,如果不能则传送给第二个处理对象...依次进行。接着让我们看几个例子。
书中的不完美的例子
虽然最开始由这个例子而懂,然而这个例子确实是不太合理的。考虑背景如下:某游戏公司的某个每日收到很多邮件,邮件种类如下:
- 来自fans:表示对公司的喜爱之情
- 来自父母:表示对该公司的游戏影响了孩子的学习,抱怨类的。
- 来自其它公司:表示想和该游戏公司合作
- 来自广告:属于垃圾邮件
- 来自fans:给CEO
- 来自父母:给法律部门(中国人看来挺夸张的)
- 来自其他公司:业务部门
- 来自广告:删除
我们可以看到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中如何使用这个责任链模式,有空可以看看