文章目录
一、概念理解
1、责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
2、责任链模式的结构
- Handler(处理者):定义一个处理请求的接口。通常包含一个处理请求的方法(如 handleRequest)和一个设置后继者的方法(如 setNext)。
- ConcreteHandler(具体处理者):实现 Handler 接口,处理它所负责的请求。可以访问它的后继者以便在自己无法处理该请求时将其传递下去。
- Client(客户端):向链上的具体处理者对象提交请求。
3、责任链模式的优点
- 降低耦合度:请求的发送者和接收者解耦,发送者不需要知道是哪一个接收者处理了请求。
- 增加灵活性:可以动态地新增或删除责任链上的处理者,修改处理者的顺序等。
- 增强可扩展性:通过添加新的具体处理者类,扩展系统的功能。
4、责任链模式的缺点
- 不保证请求一定会被处理:如果链的末尾没有处理请求,可能会导致请求被忽略。
- 调试困难:由于请求的处理是沿着链进行的,调试过程可能较为复杂。
二、代码案例
不同请假天数需要不同级别人员审核,所以将不同处理类定义成一个责任链
1、责任链执行抽象类
编写过滤责任链执行抽象类AbstractExecuteFilter.java
public abstract class AbstractExecuteFilter {
//ThreadLocal存储key
public static final String SLOT_KEY = "LeaveRequest";
//下一个拦截
protected AbstractExecuteFilter nextFilter;
//存储参数
public static ThreadLocal<Map<String, Object>> localMap = new ThreadLocal<>();
public void addNextFilter(AbstractExecuteFilter filter) {
this.nextFilter = filter;
}
public abstract boolean execute();
/**直接主管审批处理的请假天数*/
protected int MIN = 1;
/**部门经理处理的请假天数*/
protected int MIDDLE = 3;
/**总经理处理的请假天数*/
protected int MAX = 30;
}
编写参数传递类(请假类):
@Builder
public class LeaveRequest {
/**天数*/
private int leaveDays;
/**姓名*/
private String name;
}
2、设置上下文环境获取bean
根据不同的filters名动态获取对象,ExecuteFilterLoader实现ApplicationContextAware接口,
@Slf4j
@Component
public class ExecuteFilterLoader implements ApplicationContextAware {
public static ApplicationContext applicationContext;
/**
* 加载规则执行链
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
* @param applicationContext spring上下文对象
* @throws BeansException 抛出spring异常
*/
public static AbstractExecuteFilter loadExecuteFilter(List<String> filters) {
if (CollectionUtils.isEmpty(filters)) {
throw BusinessException.asBusinessException(BusinessErrorCode.ILLEGAL_ARG_ERROR);
}
AbstractExecuteFilter filter = null;
AbstractExecuteFilter next = null;
for (String filterName : filters) {
AbstractExecuteFilter bean = (AbstractExecuteFilter) applicationContext.getBean(filterName);
if (null == next) {
filter = bean;
} else {
next.addNextFilter(bean);
}
next = bean;
}
return filter;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ExecuteFilterLoader.applicationContext = applicationContext;
}
}
3、不同处理类扩展 AbstractLeaveHandler
创建三种类型的审批处理,都继承了 AbstractLeaveHandler抽象类:
/**
* 直接领导处理
*/
@Slf4j
@Component("directLeaderLeaveHandler")
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler {
@Override
public void execute() {
int leaveDays = (int) localMap.get().get("leaveDays");
if(leaveDays <= this.MIN){
System.out.println("直接主管已经处理;流程结束。");
return;
}
if(null != this.nextFilter){
this.nextFilter.execute();
}else{
System.out.println("审批拒绝!");
}
}
}
/**
* 部门领导处理
*/
@Slf4j
@Component("deptManagerLeaveHandler")
public class DeptManagerLeaveHandler extends AbstractLeaveHandler {
@Override
public void execute() {
int leaveDays = (int) localMap.get().get("leaveDays");
if(leaveDays >this.MIN && leaveDays <= this.MIDDLE){
System.out.println("部门经理已经处理;流程结束。");
return;
}
if(null != this.nextFilter){
this.nextFilter.execute();
}else{
System.out.println("审批拒绝!");
}
}
}
/**
* 总经理处理
*/
@Slf4j
@Component("gManagerLeaveHandler")
public class GManagerLeaveHandler extends AbstractLeaveHandler {
@Override
public void execute() {
int leaveDays = (int) localMap.get().get("leaveDays");
if(leaveDays > this.MIDDLE && leaveDays <= this.MAX){
System.out.println("总经理已经处理;流程结束。");
return;
}
if(null != this.nextFilter){
this.nextFilter.execute();
}else{
System.out.println("审批拒绝!");
}
}
}
4、调用
(新员工请假20天谁审批):
//要处理的责任链(直接领导、部门领导、总经理审批)
String filterConfig="directLeaderLeaveHandler,deptManagerLeaveHandler,gManagerLeaveHandler";
//入参
LeaveRequest request = LeaveRequest.builder().leaveDays(20).name("新员工").build();
//不同责任链类间通过ThreadLocal参数传递
Map<String, Object> localMap = new HashMap<>();
localMap.put(AbstractExecuteFilter.SLOT_KEY,request);
AbstractExecuteFilter.localMap.set(localMap);//传递参数
ExecuteFilterLoader.loadExecuteFilter(Arrays.asList(filterConfig.split(","))).execute();
运行结果:总经理已经处理;流程结束。
小结:调用了审批链不同环节的处理,应用责任链模式进行解耦,增强给对象指派职责的灵活性。