深入浅出基于Java的责任链模式
副标题#e#
一、引言
初看责任链模式,心里不禁想起了一个以前听过的相声:看牙。说的是一个病人看牙的时候,大夫不小心把拔下的一个牙掉进了病人嗓子里。病人因此楼上楼下的跑了许多几何科室,最后无果而终。
责任链模式就是这种“推卸”责任的模式,你的问题在我这里能办理我就办理,不可就把你推给另一个工具。至于到底谁办理了这个问题了呢?我管呢!
二、界说与布局
从名字上或许也能猜出这个模式的或许容貌——系统中将会存在多个有雷同处理惩罚本领的工具。当一个请求触发后,请求将在这些工具构成的链条中通报,直到找到最符合的“责任”工具,并举办处理惩罚。
《设计模式》中给它的界说如下:使多个工具都有时机处理惩罚请求,从而制止请求的发送者和吸收者之间的耦合干系。将这些工具连成一条链,并沿着这条链通报该请求,直到有一个工具处理惩罚它为止。
从界说上可以看出,责任链模式的提出是为了“解耦”,以应变系统需求的改观和不明晰性。
下面是《设计模式》中给出的合用范畴:
1) 有多个的工具可以处理惩罚一个请求,哪个工具处理惩罚该请求运行时刻自动确定。
2) 你想在不明晰指定吸收者的环境下,向多个工具中的一个提交一个请求。
3) 可处理惩罚一个请求的工具荟萃应被动态指定。
责任链模式真的能给发送者和吸收者之间解耦(这仿佛很神奇)吗?先来看下它的构成脚色。这个问题我会在下面提及。
责任链模式由两个脚色构成:
1) 抽象处理惩罚者脚色(Handler):它界说了一个处理惩罚请求的接口。虽然对付链子的差异实现,也可以在这个脚色中实现后继链。
2) 详细处理惩罚者脚色(Concrete Handler):实现抽象脚色中界说的接口,并处理惩罚它所认真的请求。假如不能处理惩罚则会见它的后继者。
至于类图不放也罢。究竟就是一个担任可能实现。
三、纯与不纯
责任链模式的纯与不纯的区别,就像黑猫、白猫的区别一样。不要决心的去使本身的代码来切合一个模式的公式。只要可以或许使代码低落耦合、提高重用,满意系统需求并能很好的适应变革就好了。正所谓:管它黑猫白猫,抓住老鼠就是好猫!
纯的责任链模式,划定一个详细处理惩罚者脚色只能对请求作出两种行动:本身处理惩罚;传给下家。不能呈现处理惩罚了一部门,把剩下的传给了下家的环境。并且请求在责任链中必需被处理惩罚,而不能呈现无果而终的了局。
反之,则就是不纯的责任链模式。
不纯的责任链模式还算是责任链模式吗?好比一个请求被捕捉后,每个详细处理惩罚者都实验去处理惩罚它,不管功效如何都将请求再次转发。我认为这种方法的实现,算不算是责任链模式的一种倒不重要,重要的是我们也能从中体味到责任链模式的思想:通过将多个处理惩罚者之间成立接洽,来到达请求与详细的某个处理惩罚者的解耦。
下面的例子就是回收了上面提到的“不纯的责任链模式”。
#p#副标题#e#
四、举例
这个例子来历于项目中我方才完成的一个小成果点——“代号自动生成器”。在项目中存在许多处所,好比:员工工号、档案代号,要求客户在利用时输入。而这些代号对付一个特定的企业可能种别,往往有必然的法则。因此可以让用户在系统参数中维护必然的法则,然后通过“代号自动生成器”来给用户生成代号。
按照初期需求,用户代号中往往存在以下几种变换元素:年份、月份、日期、流水号。由于需求较量简朴,因此思量到用户大概存在其他变换元素,所以我规划在“被第一颗子弹击中”后重构一下现有的布局。下面就是我在脑子中演绎过的利用责任链模式的重构。
这里只用来说明下责任链模式的布局和利用,因此不浮现成果细节。
//这是抽象处理惩罚者脚色
public interface CodeAutoParse {
//这里就是统一的处理惩罚请求利用的接口
String[] generateCode(String moduleCode, int number, String rule,String[] target) throws BaseException;
}
//这个为处理惩罚日期利用的详细处理惩罚者
public class DateAutoParse implements CodeAutoParse{
//获取当前时间
private final Calendar currentDate = Calendar.getInstance();
//这里用来注入下一个处理惩罚者,系统中回收的是Spring来打点的
private CodeAutoParse theNextParseOfDate;
public void setTheNextParseOfDate(CodeAutoParse theNextParseOfDate){
this.theNextParseOfDate = theNextParseOfDate ;
}
/*
*实现的处理惩罚请求的接口
*这个接口首先判定用户界说的名目是否有流水号,有则理会,没有则跳过
*下传到下一个处理惩罚者
*/
public String[] generateCode(String moduleCode, int number, String rule, String[] target)
throws BaseException {
//这里省略了处理惩罚的业务
……
if(theNextParseOfDate != null)
return theNextParseOfDate.generateCode(moduleCode , number , rule, target)
else
return target;
}
其它详细处理惩罚者也是如此的布局,每一个内里都配置有一个用来存放下一个处理惩罚者的引用,不管你有没有下一个处理惩罚者。
#p#分页标题#e#
其实责任链模式自己的布局和利用都没有什么,就是一个担任可能实现。在处理惩罚请求的时候,凭据划定去挪用下一个处理惩罚者。可是怎么来维护这样一条链子呢?
《设计模式》一书中仅仅说必需本身引入它,可以参考利用list可能map来举办注册。而在上面我利用spring来打点详细处理惩罚者脚色的引入。当有了新的处理惩罚者需要添加的时候,仅仅需要修改下设置文件。
五、其他
责任链模式利益,上面已经浮现出来了。无非就是低落了耦合、提高了机动性。可是责任链模式大概会带来一些特另外机能损耗,因为它要从链子开头开始遍历。