责任链模式

1、定义

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

  • 责任链模式为请求创建一个接收者对象链,每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把请求传给下一个接收者,依此类推
  • 责任链模式避免了请求的发送者和接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

2、UML 图


优点:

  • 降低耦合度。它将请求的发送者和接收者解耦
  • 简化了对象,使得对象不需要知道链的结构
  • 增强给对象指派职责的灵活性,允许动态地新增或者删除责任链
  • 增加新的请求处理类方便

缺点:

  • 不能保证请求一定被接收;
  • 系统性能将受到一定影响,调试时不方便,可能会造成循环调用

3、示例

抽象处理者:

public abstract class Handler {
    private Handler next;
    public Handler getNext(){
        return next;
    }
    public void setNext(Handler next) {
        this.next = next;
    }
    public abstract void handle(String message);
}

具体处理者:

public class MangerHandler extends Handler {
    @Override
    public void handle(String message) {
        if ("补休".equals(message)) {
            System.out.println("经理同意补休申请");
        }else {
            System.out.println("经理无法处理,转给总监");
            getNext().handle(message);
        }
    }
}
public class CTOHandler extends Handler {
    @Override
    public void handle(String message) {
        if ("年假".equals(message)) {
            System.out.println("总监同意年假申请");
        }else {
            System.out.println("总监无法处理,转给人事");
            getNext().handle(message);
        }
    }
}
public class HRHandler  extends Handler{

    @Override
    public void handle(String message) {
        if ("离职".equals(message)) {
            System.out.println("HR 同意");
        }else {
            System.out.println("无法处理");
        }
    }

    public static void main(String[] args) {
        MangerHandler mangerHandler = new MangerHandler();
        CTOHandler ctoHandler = new CTOHandler();
        HRHandler hrHandler = new HRHandler();
        mangerHandler.setNext(ctoHandler);
        ctoHandler.setNext(hrHandler);
        mangerHandler.handle("补休");
        System.out.println("=====");
        mangerHandler.handle("年假");
        System.out.println("=====");
        mangerHandler.handle("离职");
    }
}
输出:
经理同意补休申请
=====
经理无法处理,转给总监
总监同意年假申请
=====
经理无法处理,转给总监
总监无法处理,转给人事
HR 同意

4、应用场景

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定
  • 在不明确指定接收者的情况下,向多个对象中的某一个对象提交一个请求
  • 可动态指定一组对象的处理请求

Tomcat中的Filter就是使用了责任链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现javax.servlet.Filter接口。

spring 的过滤器