概念
责任链模式,听起来好像挺复杂的,但是其实都是生活中常见的一些东西。
今天洪爵来给大家形象生动的讲一下责任链模式。
现在要求输入一个字符串,不包含敏感词,长度在5-10字符之间,全中文… …
那么对于这样一个字符串,我们有很多需要过滤的信息。这个时候就要考虑用责任链了。
责任链模式是一个设计模式,在这个模式中,责任链可以看做是一个单链表,单链表中的每一个节点可以看成是一个对象,通过next指针指向它的下一个对象,从而形成的一条链结构。
比如说这条链中的第一个节点对象是负责检查传进来的字符串有没有敏感词,第二个节点对象是负责检查这个字符串有没有英文字母,第三个节点对象负责检查这个字符串符不符合字数要求… …
那么现在进来一个字符串,就要经过重重关卡,如果有一条不满足,他都是不通过的。
了解过JAVA WEB的童鞋都知道,像拦截器,过滤器等都是使用到了责任链模式。
像下图,同样是一个责任链模式。
责任链模式是一种对象行为型模式,它的主要优点:
1、低耦合,对象无需知道,到底是哪一个对象处理了它的请求,并且对它屏蔽了整个链结构。
2、增强了可扩展性,可以随时添加新的请求处理类放入链中,满足了开闭原则。
3、当工作流程发生变化,我们可以随时调整链中成员的次序。
4、简化了对象之间的连接,每个对象只需要保持后一个对象的引用。
5、每个类只需要处理自己的工作,明确职责,责任分担,符合类的单一职责原则。
模式的结构
责任链有以下几种角色:
抽象处理者Abstract handler:定义抽象方法或者通用的方法,建立通往下一个流程的节点。
具体处理者Concrete Handler:具体实现抽象处理者的方法,可处理则处理,不可处理交给下一个节点。
请求者Request:向责任链链头的具体处理者提交请求,不关系处理细节和传递过程。
场景
我们模拟一个场景,你现在在洪爵科技公司工作,某天你要请假啦,然后你在OA系统上提交了申请。
审核流程
请假1天的,直属上级可以直接审批
请假7天及以内的,主管可审批
请假30及以内的,总监可审批
大于30天的,不可审批
类图
我们抽象处理请假的类:LeaveHandler
然后具体的处理请假请求的人:
直属leader处理请假类:DirectLeaderLeaveHandler
主管处理请假类:ManagerLeaveHandler
总监处理请假类:ChiefHandler
员工提交请假请求类:LeaveRequest
具体代码实现:
抽象处理请假类 + 具体实现类
// LeaveHandler.java
public abstract class LeaveHandler {
protected static int minDays = 1; // 直属leader可以处理的最大天数
protected static int weekDays = 7; // 主管可以处理的最大天数
protected static int monthDays = 30; // 总监可以处理的最大天数
protected int dealMaxDays; // 可以处理的最大请假天数
protected String handlerName; // 职位(直属leader, 主管, 总监)
protected LeaveHandler nextHandler; // 下一个处理节点
public LeaveHandler(String handlerName, int dealMaxDays) {
this.handlerName = handlerName;
this.dealMaxDays = dealMaxDays;
}
// 设置下一个审批节点
public void setNextHandler(LeaveHandler nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请假请求
protected void handlerRequest(LeaveRequest leaveRequest) {
// 如果可以处理,则审批
if(this.dealMaxDays >= leaveRequest.getLeaveDays()) {
System.out.println(this.handlerName + ": 审批完成!");
return;
}
// 不可处理的话, 交给上级
if(null != this.nextHandler) {
this.nextHandler.handlerRequest(leaveRequest);
} else {
System.out.println("审批失败!");
}
}
}
// DirectLeaderLeaveHandler.java 直属leader处理请求类
public class DirectLeaderLeaveHandler extends LeaveHandler {
public DirectLeaderLeaveHandler(String handlerName, int dealMaxDays) {
super(handlerName, dealMaxDays);
}
}
// ManagerLeaveHandler.java 主管处理请求类
public class ManagerLeaveHandler extends LeaveHandler {
public ManagerLeaveHandler(String handlerName, int dealMaxDays) {
super(handlerName, dealMaxDays);
}
}
// ChiefHandler.java 总监处理请求类
public class ChiefHandler extends LeaveHandler {
public ChiefHandler(String handlerName, int dealMaxDays) {
super(handlerName, dealMaxDays);
}
}
员工请假请求类
// LeaveRequest.java
@Data
@Builder
public class LeaveRequest {
private int workId; // 员工号
private String name; // 员工姓名
private int leaveDays; // 请假天数
}
最后我们写个main函数来测试下:
public class Demo {
public static void dealWithLeaveRequest(LeaveRequest leaveRequest) {
DirectLeaderLeaveHandler direct = new DirectLeaderLeaveHandler("直属leader", LeaveHandler.minDays);
ManagerLeaveHandler manager = new ManagerLeaveHandler("主管", LeaveHandler.weekDays);
ChiefHandler chief = new ChiefHandler("总监", LeaveHandler.monthDays);
// 直属leader的上级是主管
direct.setNextHandler(manager);
// 主管的上级是总监
manager.setNextHandler(chief);
// 首先尝试让直属leader审批
direct.handlerRequest(leaveRequest);
}
public static void main(String[] args) {
LeaveRequest leaveRequest = LeaveRequest.builder()
.workId(3693321)
.name("Knight洪爵")
.leaveDays(30) // 请假天数
.build();
dealWithLeaveRequest(leaveRequest);
}
}
当我们leaveDays输入1的时候,结果为:直属leader: 审批完成!
当我们leaveDays输入2的时候,结果为:主管: 审批完成!
当我们leaveDays输入7的时候,结果为:主管: 审批完成!
当我们leaveDays输入8的时候,结果为:总监: 审批完成!
当我们leaveDays输入30的时候,结果为:总监: 审批完成!
当我们leaveDays输入31的时候,结果为:审批失败!
本篇文章就到这里啦~~希望洪爵讲的责任链对你有所帮助呀~
愿每个人都能带着怀疑的态度去阅读文章并探究其中原理。
道阻且长,往事作序,来日为章。
期待我们下一次相遇!