设计模式-责任链模式(Chain of Responsibility Pattern)

857 阅读3分钟

Github 源码地址

23种设计模式总览

创建型模式

结构型模式

行为型模式

定义

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

优缺点

优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。

缺点:  
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。

场景

现实中,请假的OA申请,请假天数如果是半天到1天,可能直接主管批准即可;
如果是1到3天的假期,需要部门经理批准;
如果是3天到30天,则需要总经理审批;
大于30天,正常不会批准。

实现

  • 员工提交请求类:LeaveRequest。
  • 抽象的请假责任处理类:AbstractLeaveHandler。
  • 直接主管审批处理类:DirectLeaderLeaveHandler。
  • 部门经理处理类:DeptManagerLeaveHandler。
  • 总经理处理类: GManagerLeaveHandler。
//员工提交请求类
public class LeaveRequest {
    /**
     * 天数
     */
    private int leaveDays;
    /**
     * 姓名
     */
    private String name;

    public LeaveRequest(int leaveDays, String name) {
        this.leaveDays = leaveDays;
        this.name = name;
    }

    public int getLeaveDays() {
        return leaveDays;
    }

    public void setLeaveDays(int leaveDays) {
        this.leaveDays = leaveDays;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
//请假责任链抽象处理类
abstract public class AbstractLeaveHandler {
    /**
     * 直接主管审批处理的请假天数
     */
    public int MIN = 1;
    /**
     * 部门经理处理的请假天数
     */
    public int MIDDLE = 3;
    /**
     * 总经理处理的请假天数
     */
    public int MAX = 30;

    /**
     * 下一个处理节点(即更高级别的领导)
     */
    public AbstractLeaveHandler nextHandler;

    /**
     * 设置下一节点
     */
    public void setNextHandler(AbstractLeaveHandler handler) {
        this.nextHandler = handler;
    }

    /**
     * 处理请假的请求,子类实现
     */
    abstract public void handlerRequest(LeaveRequest request);
}
//直接主管处理类
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler {

    @Override
    public void handlerRequest(LeaveRequest request) {
        if (request.getLeaveDays() <= this.MIN) {
            System.out.println("直接主管:已经处理;流程结束。");
            return;
        }

        if (null != this.nextHandler) {
            this.nextHandler.handlerRequest(request);
        } else {
            System.out.println("审批拒绝!");
        }
    }
}
// 部门经理处理类
public class DeptManagerLeaveHandler extends AbstractLeaveHandler {

    @Override
    public void handlerRequest(LeaveRequest request) {
        if (request.getLeaveDays() > this.MIN && request.getLeaveDays() <= this.MIDDLE) {
            System.out.println("部门经理:已经处理;流程结束。");
            return;
        }

        if (null != this.nextHandler) {
            this.nextHandler.handlerRequest(request);
        } else {
            System.out.println("审批拒绝!");
        }
    }
}
//总经理处理类
public class GManagerLeaveHandler extends AbstractLeaveHandler {

    @Override
    public void handlerRequest(LeaveRequest request) {
        if (request.getLeaveDays() > this.MIDDLE && request.getLeaveDays() <= this.MAX) {
            System.out.println("总经理:已经处理;流程结束。");
            return;
        }

        if (null != this.nextHandler) {
            this.nextHandler.handlerRequest(request);
        } else {
            System.out.println("审批拒绝!");
        }
    }
}

演示

public class Test {
    public static void main(String[] args) {
        LeaveRequest request1 = new LeaveRequest(1, "小明");
        LeaveRequest request2 = new LeaveRequest(3, "小明");
        LeaveRequest request3 = new LeaveRequest(7, "小明");

        AbstractLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler();
        DeptManagerLeaveHandler deptManagerLeaveHandler = new DeptManagerLeaveHandler();
        GManagerLeaveHandler gManagerLeaveHandler = new GManagerLeaveHandler();

        //直接主管下一级为部门经理
        directLeaderLeaveHandler.setNextHandler(deptManagerLeaveHandler);
        //部门经理下一级为总经理
        deptManagerLeaveHandler.setNextHandler(gManagerLeaveHandler);

        //小明请假直接领导处理
        directLeaderLeaveHandler.handlerRequest(request1);
        directLeaderLeaveHandler.handlerRequest(request2);
        directLeaderLeaveHandler.handlerRequest(request3);
    }
}
  • 1天,运行输出: 直接主管:已经处理;流程结束。
  • 3天,运行输出: 部门经理:已经处理;流程结束。
  • 7天,运行输出: 总经理:已经处理;流程结束。

总结

责任链主要重在责任分离处理,让各个节点各司其职。
责任链上的各个节点都有机会处理事务,但是也可能不会受理请求。
责任链比较长,调试时可能会比较麻烦。
责任链一般用于处理流程节点之类的实际业务场景中。