设想一个场景,需要对一批从客户端来的数据进行多种不同的操作,我们会使用多个不同的类负责不同的操作,而不是使用一个类集成所有操作,这样做能让代码松耦合且简洁。
这些类被称为处理器,第一个处理器会接收请求,如果它需要执行操作则会进行一次调用,如果不需要则会将请求传递给第二个处理器。类似地,第二个处理器确认并将请求传递给责任链中的下一个处理器。
- 目的
责任链模式可以让处理器按以下方式处理:如果需要则处理请求,否则将请求传递给下一个处理器。 -
实现
所示的类图描述了责任链模式的结构和行为:
image.png
类图中主要包含以下类:
- Client(客户端):客户端是使用责任链模式的应用程序的主要结构。它的职责是实例化一个处理器的链,然后在第一个对象中调用
handleRequest
方法。 - Handler(处理器):这是一个抽象类,提供给所有实际处理器进行继承。它拥有一个
handleRequest
方法,用来接收需要处理的请求。 - ConcreteHandler(具体处理器):这是一个实现了
handleRequest
方法的具体类。每一个具体处理器都维持一个引用,指向链中下一个具体处理器,需要检查它自身是否能处理这个请求,不能就将请求传递给链中的下一个具体处理器。
每一个处理器需要实现一个方法,该方法被客户端所使用,并能够设置下一个处理器,当它无法处理请求时,将请求传给下一个处理器。这个方法可以加入到Handle
基类当中。
/**
* 设置下一节点
*
* @param handler
*/
public void setNextHandler(AbstractLeaveHandler handler) {
this.nextHandler = handler;
}
在每一个ConcreteHandler类中,我们实现下列代码,检查它是否能处理请求,不能则会传递请求:

客户端负责在调用链头之前建立处理器链。这次调用会被传递,直到发现了能正确处理这个请求的处理器。
实例
这里一员工请假为例:
现实中,请假的OA申请,请假天数如果是半天到1天,可能直接主管批准即可;
如果是1到3天的假期,需要部门经理批准;
如果是3天到30天,则需要总经理审批;
大于30天,正常不会批准。
主要类
- 员工提交请求类:LeaveRequest
- 抽象的请假责任处理类:AbstractLeaveHandler
- 直接主管审批处理类:DirectLeaderLeaveHandler
- 部门经理处理类:DeptManagerLeaveHandler
- 总经理处理类: GeneralManagerLeaveHandler
实现
员工请求发起申请到抽象的责任处理类中,根据员工的请假天数,对应的处理类完成处理。
每一个责任处理类设置下面的节点。自身处理不了则传递给下一个节点处理。
员工提交请求类LeaveRequest.java
/**
* @author Jay Mitter
* @description: 员工提交请求类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LeaveRequest {
/**
* 天数
*/
private int leaveDays;
/**
* 姓名
*/
private String name;
}
请假责任链抽象处理类AbstractLeaveHandler.java
/**
* @author: Jay Mitter
* @description: 请假责任链抽象处理类
*/
public abstract class AbstractLeaveHandler {
/**
* 直接主管审批处理的请假天数
*/
protected static final int MIN = 1;
/**
* 部门经理处理的请假天数
*/
protected static final int MIDDLE = 3;
/**
* 总经理处理的请假天数
*/
protected static final int MAX = 30;
/**
* 领导名称
*/
protected String handlerName;
/**
* 下一个处理节点(即更高级别的领导)
*/
protected AbstractLeaveHandler nextHandler;
/**
* 设置下一节点
*
* @param handler
*/
public void setNextHandler(AbstractLeaveHandler handler) {
this.nextHandler = handler;
}
/**
* 处理请假的请求,子类实现
* @param request
*/
public abstract void handlerRequest(LeaveRequest request);
}
直接主管处理类DirectLeaderLeaveHandler.java
/**
* @author: Jay Mitter
* @description: 直接主管处理类
*/
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler {
public DirectLeaderLeaveHandler(String name) {
this.handlerName = name;
}
@Override
public void handlerRequest(LeaveRequest request) {
if (request.getLeaveDays() <= MIN) {
System.out.println("直接主管: " + handlerName + ",已经处理;流程结束。");
return;
}
if (null != this.nextHandler) {
this.nextHandler.handlerRequest(request);
} else {
System.out.println("审批拒绝!");
}
}
}
部门经理处理类DeptManagerLeaveHandler.java
/**
* @author: Jay Mitter
* @description: 部门经理处理类
*/
public class DeptManagerLeaveHandler extends AbstractLeaveHandler {
public DeptManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
public void handlerRequest(LeaveRequest request) {
if (request.getLeaveDays() > MIN && request.getLeaveDays() <= MIDDLE) {
System.out.println("部门经理: " + handlerName + ",已经处理;流程结束。");
return;
}
if (null != this.nextHandler) {
this.nextHandler.handlerRequest(request);
} else {
System.out.println("审批拒绝!");
}
}
}
总经理处理类GeneralManagerLeaveHandler.java
/**
* @author: Jay Mitter
* @description: 总经理处理类
*/
public class GeneralManagerLeaveHandler extends AbstractLeaveHandler {
public GeneralManagerLeaveHandler(String name) {
this.handlerName = name;
}
@Override
public void handlerRequest(LeaveRequest request) {
if (request.getLeaveDays() > MIDDLE && request.getLeaveDays() <= MAX) {
System.out.println("总经理: " + handlerName + ",已经处理;流程结束。");
return;
}
if (null != this.nextHandler) {
this.nextHandler.handlerRequest(request);
} else {
System.out.println("审批拒绝!");
}
}
}
测试:
/**
* 行为型模型——责任链模式
*/
@Test
public void testBehaviorDutyChain() {
LeaveRequest request = LeaveRequest.builder().leaveDays(40).name("小明").build();
AbstractLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler("县令");
DeptManagerLeaveHandler deptManagerLeaveHandler = new DeptManagerLeaveHandler("知府");
GeneralManagerLeaveHandler generalManagerLeaveHandler = new GeneralManagerLeaveHandler("京兆尹");
directLeaderLeaveHandler.setNextHandler(deptManagerLeaveHandler);
deptManagerLeaveHandler.setNextHandler(generalManagerLeaveHandler);
directLeaderLeaveHandler.handlerRequest(request);
}
网友评论