实际上,责任链模式是 一个请求(不管是用户的请求,系统的请求还是哪里来的请求),可以有很多个接收者,这些接受者自身每个都有适合处理这个请求的场景,如果满足自身的场景自己就会处理,如果不满足自己的使用场景就会调用下一个接收者的引用,并把请求传递给下一个接收者来处理,下一个接受者以此类推,所以责任链上的每一环都有对下一环的引用。
比如Struts2的拦截器,一个Action过来,第一道接收者是处理字符编码,如果不满足字符编码,我们进行字符编码的转换,然后如果满足放行条件第一道接收者就会调用下一个接收者,来进行密码的校验,如果第二道校验通过,会自动调用第三道接收者,第三道接收者开始校验权限,权限通过则放行,不通过则返回失败信息…
我们完全不需要知道它一环一环是怎么调用的,我们只需要知道它有这些功能,如果有一项不匹配(比如密码不对),肯定会在某一环被拦截下来,我们只需要把需求发送到责任链上接收的一端,就无需再关心它的实现细节。
接下来用另一个例子加深对责任链的理解,工厂流水线,自动化的,主要工作内容是自动化分拣出各种品质(个头大小)的苹果,贴上不同的价码销往不同的地方:
1.首先新建一个产品类,apple
public class Apple
{
private int weight;//存放苹果的重量,单位是克
public Apple(int weight){
this.weight = weight;
}
public int getWeight(){
return weight;
}
}
2.建立一个分拣苹果设备需要继承的共同抽象类,里面主要写一些公共参数和方法,规范实现方法。
public abstract class Weighing{
public Weighing nextWeighing;//存放对下一分拣设备的引用
public void setWeighing(Weighing nextWeighing){
this.nextWeighing = nextWeighing;
}
public abstract void doWeighing(Apple apple);
}
3.建立一个优质苹果分拣机,并继承抽象类
public class WeighingOfQuality extends Weighing{
@Override
public void doWeighing(Apple apple) {//传入产品
if(apple != null){
if(apple.getWeight() >= 250){//重量为克,如果合格则进行包装
System.out.println("优质苹果,打包成果篮,销往高档礼品超市");
}else{//否则调用下一个分拣机器进行处理
nextWeighing.doWeighing(apple);
}
}
}
}
4.建立一个分拣中等质量苹果的机器,继承抽象类
public class WeighingOfMiddling extends Weighing{
@Override
public void doWeighing(Apple apple) {
if(apple != null){
if(apple.getWeight() >= 190){//重量为克,如果合格则进行包装
System.out.println("中等品质苹果,装进水果框,销往水果商店");
}else{//否则调用下一个分拣机器进行处理
nextWeighing.doWeighing(apple);
}
}
}
}
5.建立一个分拣普通品质苹果的机器,继承抽象类
public class WeighingOfOrdinary extends Weighing{
@Override
public void doWeighing(Apple apple) {
if(apple != null){
if(apple.getWeight() < 190){//重量为克,如果合格则进行包装
System.out.println("普通品质苹果,打包成箱,销往批发摊贩");
}else{//否则发出警告,分拣异常,因为这已经是最后一个标准的分拣设备,再不符合条件就是产生了异常
System.out.println("分拣异常");
}
}
}
}
6.流水线现在开始开工
public class Test {
public static void main(String[] args){
Apple apple = new Apple(234);//提前预置一个苹果的重量,单位是克
Apple apple2 = new Apple(121);
Apple apple3 = new Apple(267);
Weighing wq = new WeighingOfQuality();//优质苹果分拣机准备就绪
Weighing wm = new WeighingOfMiddling();//中等品质苹果分拣机准备就绪
Weighing wo = new WeighingOfOrdinary();//普通品质苹果分拣机准备就绪
wq.setWeighing(wm);//优质分拣机传入对下一个分拣设备(中等品质)的引用
wm.setWeighing(wo);//中等品质分拣机传入对下一个分拣设备(普通品质)的引用
wq.doWeighing(apple);//只需要将苹果传入责任链的入口,就会自动进行处理,自己无法处理就会调用下一个设备的引用,并把苹果(请求)传到下一个设备
wq.doWeighing(apple2);
wq.doWeighing(apple3);
}
}
控制台输出:
中等品质苹果,装进水果框,销往水果商店
普通品质苹果,打包成箱,销往批发摊贩
优质苹果,打包成果篮,销往高档礼品超市
现在就实现了责任链模式,即使传入的请求不符合其自身处理的条件,其就会原封不动的将其传入下一个处理者,下一个处理者以此类推,责任链能够继续下去的重要一点就是,每个处理者都包含对下一个处理者的引用,因此才能一环扣一环,形成链结构。
优点:
像一开始就说过,我们无需关心处理细节,只需要知道这条链上的功能是我们想要的,我们把请求传过去就可以了,具体的细节被隐藏了,我们不会知道最终是哪个处理者处理了我们的请求,也实现了请求者和处理者之间的解耦,我们只需要更改被调用的顺序——>wq.setWeighing(wm);//优质分拣机传入对下一个分拣设备(中等品质)的引用 wm.setWeighing(wo);//中等品质分拣机传入对下一个分拣设备(普通品质)的引用
即能改变处理的流程和先后顺序,而且方便我们增加扩展新的处理者。
缺点:
代码调试的时候有可能产生混乱,现在举例自然是怎么贴合理解怎么来,但是实际业务逻辑相对更复杂,在隐藏了处理细节的同时,对我们代码调试,找错,也增加了难度。