在一些业务场景下,为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。在责任链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过A处理器处理,然后再把请求传递给B处理器,B处理器处理完后再传递给C处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
这里以工厂的流水线生产为例,来分析研究一下责任链模式如何实现。
假设一台手机的各种零部件已经制造完成,具体的手机的组装过程是这样的:
如果写一段程序来模拟这个组装过程,选择使用责任链模式来实现应该怎么实现呢?
1、声明一个抽象的分步组装的处理类,定义抽象的组装方法和指向下一步的处理者的引用 ;
/**
* 抽象的分步组装处理类
*/
public abstract class AbstractHandler {
private AbstractHandler abstractHandler;
public AbstractHandler getAbstractHandler() {
return abstractHandler;
}
public void next(AbstractHandler abstractHandler) {
this.abstractHandler = abstractHandler;
}
public abstract void make();
}
2、声明具体的处理者,即主板安装的处理者,继承了抽象的分步组装处理器,实现抽象的组装方法,即主板的安装;
/**
* 主板安装
*/
public class MotherboardHandler extends AbstractHandler {
@Override
public void make() {
System.out.println("主机安装完成");
if (this.getAbstractHandler() != null) {
this.getAbstractHandler().make();
}
}
}
3、声明第二具体的处理者,即电池安装的处理者,继承了抽象的分步组装处理器,实现抽象的组装方法,即电池的安装;
/**
* 电池安装
*/
public class BatteryHandler extends AbstractHandler{
@Override
public void make() {
System.out.println("电池组装完成");
if (this.getAbstractHandler() != null) {
this.getAbstractHandler().make();
}
}
}
4、声明具体的处理者,即屏幕安装的处理者,继承了抽象的分步组装处理器,实现抽象的组装方法,即屏幕的安装;
/**
* 屏幕安装
*/
public class ScreenHandler extends AbstractHandler{
@Override
public void make() {
System.out.println("屏幕安装完成");
if (this.getAbstractHandler() != null) {
this.getAbstractHandler().make();
}
}
}
5、声明具体的处理者,即整机上电测试的处理者,继承了抽象的分步组装处理器,实现抽象的组装方法,即上电测试;
/**
* 上电测试
*/
public class TestHandler extends AbstractHandler {
@Override
public void make() {
System.out.println("上电测试通过");
if (this.getAbstractHandler() != null) {
this.getAbstractHandler().make();
}
}
}
6、声明一个客户端,也就是手机组装生产线,主要业务也就是把组装过程的每一步整合起来,这样一条完整的手机组装生产线就搭建好了,可以开始生产活动了;
/**
* 生产线
*/
public class ProductLine {
public static void main(String[] args) {
AbstractHandler step1=new MotherboardHandler();
AbstractHandler step2=new BatteryHandler();
AbstractHandler step3=new ScreenHandler();
AbstractHandler step4=new TestHandler();
step1.next(step2);
step2.next(step3);
step3.next(step4);
step1.make();
}
}
科技进步了,手机不仅能接电话和打电话,还能拍照,那么原来的手机组装生产线就需要升级,增加摄像头的组装。面对这样的扩展需求,应该怎么实现呢?很简单,往下看:
1、增加一个工位,即声明一个摄像头安装的处理类,同样继承于抽象的分步组装处理器,实现抽象的组装方法,即摄像头安装;
/**
* 报像头安装
*/
public class CameraHandler extends AbstractHandler{
@Override
public void make() {
System.out.println("摄像头安装完成");
if (this.getAbstractHandler() != null) {
this.getAbstractHandler().make();
}
}
}
2、原来的生产线的工作顺序调整一下,在主机安装完成后,增加一步摄像头的组装,就可以了;原来的其他步骤的工作逻辑不变,完全符合开闭原则。
/**
* 生产线
*/
public class ProductLine {
public static void main(String[] args) {
AbstractHandler step1=new MotherboardHandler();
AbstractHandler step1_2=new CameraHandler();
AbstractHandler step2=new BatteryHandler();
AbstractHandler step3=new ScreenHandler();
AbstractHandler step4=new TestHandler();
step1.next(step2);
step1.next(step1_2);
step1_2.next(step2);
step2.next(step3);
step3.next(step4);
step1.make();
}
}
责任链模式适用于处理具有依次顺序、多个步骤的场景,如:
责任链模式在Spring中有很多应用场景:
在使用责任链模式时,需要注意链中节点的数量需要控制,避免出现超长链的情况。一般做法是在Handler中设置一个最大的节点数量,在setNext()方法中判断是否已经是超过其阈值,超过则不允许建立,避免无意识的破坏系统性能。