1. 概念:

责任链模式的核心: 使多个对象(一组服务)都有机会处理同一个请求, 并且这一组服务在执行处理的时候要有先后关系. 咱们公司在发布项目的需要各级大佬审批, 其实就可以使用责任链实现。
2. 一坨代码实现:

这里从上到下分别判断了在指定时间范围内由不同的人员进行审批,这样实现起来比较简单,但这样的实现就很难进行扩展。
3. 责任链模式重构代码:
下图是责任链结构的核心部分, 实现了统一抽象类的不同规则, 再进行编排, 就形成了一条链路.

3.1 链路抽象类定义:
public abstract class ApprovalLink {protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 时间格式化protected String levelUserName; // 级别人员姓名private ApprovalLink next; // 责任链public ApprovalLink(String levelUserName) {this.levelUserName = levelUserName;}public ApprovalLink next() {return next;}public ApprovalLink appendNext(ApprovalLink next) {this.next = next;return this;}/*抽象审批方法*/public abstract void approval(String publishId, Date publishDate);/*** 链路入口** @param publishId* @param publishDate* @return*/public Result run(String publishId, Date publishDate) {try {approval(publishId, publishDate);ApprovalLink link = this;while (true) {link = link.next();if (link == null) {return new Result("200", "单号:", publishId, " 状态:审批完成");}link.approval(publishId, publishDate);}} catch (RuntimeException e) {return new Result("500", "单号:", publishId, " 状态: " + e.getMessage());}}}
3.2 审批实现类:
// 三级审批public class FirstApprovalLink extends ApprovalLink {public FirstApprovalLink(String levelUserName) {super(levelUserName);}@Overridepublic void approval(String publishId, Date publishDate) {// 三级审批人log.info("三级审批开始...并自动通过 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);}}// 二级审批public class SecondAuthLink extends ApprovalLink {private Date beginDate = f.parse("2021-04-01 00:00:00");private Date endDate = f.parse("2021-04-29 23:59:59");public SecondAuthLink(String levelUserName) throws ParseException {super(levelUserName);}@Overridepublic void approval(String publishId, Date publishDate) {log.info("二级审批开始... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);if (publishDate.before(beginDate) || publishDate.after(endDate)) {log.info("二级审批通过... 发布单id:{},审批人:系统自动通过,审批时间:{};", publishId, publishDate);return;}if (ThreadLocalRandom.current().nextInt(0, 2) == 0) {log.info("二级审批未通过");throw new RuntimeException("二级审批未通过");}log.info("二级审批通过... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);}}// 一级审批public class ThirdAuthLink extends ApprovalLink {private Date beginDate = f.parse("2021-04-20 00:00:00");private Date endDate = f.parse("2021-04-22 23:59:59");public ThirdAuthLink(String levelUserName) throws ParseException {super(levelUserName);}@Overridepublic void approval(String publishId, Date publishDate) {log.info("一级审批开始... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);if (publishDate.before(beginDate) || publishDate.after(endDate)) {log.info("一级审批通过... 发布单id:{},审批人:系统自动通过,审批时间:{};", publishId, publishDate);return;}if (ThreadLocalRandom.current().nextInt(0, 2) == 0) {log.info("一级审批未通过");throw new RuntimeException("一级审批未通过");}log.info("一级审批通过... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);}}
3.3 测试验证:
public void method() throws ParseException {ApprovalLink first = new FirstApprovalLink("组长");ApprovalLink second = new SecondAuthLink("总监");ApprovalLink third = new ThirdAuthLink("CTO");second.appendNext(third);first.appendNext(second);log.info("测试结果:{}", JSON.toJSONString(first.run("202104251730010001", new Date())));}
4. 项目中使用:
5. Servlet中的Filter
filter也是典型的责任链模式,是基于回调函数执行的, 在每一个过滤器执行完业务逻辑之后,都会调用FilterChain类, 而FilterChain中也会显示的调用下一个过滤器。
5.1 处理器接口定义:
public interface AqrHandler<T> {void doHandler(T t, AqrHandlerChain chain, String trace);}
5.2 处理器实现类:
public class Handler1 implements AqrHandler<List<Integer>> {@Overridepublic void doHandler(List<Integer> integers, AqrHandlerChain chain, String trace) {Iterator<Integer> iterator = integers.iterator();while (iterator.hasNext()) {Integer next = iterator.next();if (next == 3) {iterator.remove();}}chain.doHandler(integers,trace);}}public class Handler2 implements AqrHandler<List<Integer>> {@Overridepublic void doHandler(List<Integer> integers, AqrHandlerChain chain, String trace) {Iterator<Integer> iterator = integers.iterator();while (iterator.hasNext()) {Integer next = iterator.next();if (next == 6) {iterator.remove();}}chain.doHandler(integers,trace);}}public class Handler3 implements AqrHandler<List<Integer>> {@Overridepublic void doHandler(List<Integer> integers, AqrHandlerChain chain, String trace) {Iterator<Integer> iterator = integers.iterator();while (iterator.hasNext()) {Integer next = iterator.next();if (next == 9) {iterator.remove();}}chain.doHandler(integers,trace);}}
5.3 责任链:
public class AqrHandlerChain<T> {/*** 处理器集合*/private List<AqrHandler> handlers = new ArrayList<>();/*** 处理器索引下标*/private int idx = 0;/*** 添加处理器** @param filter*/public void add(AqrHandler filter) {handlers.add(filter);}public void doHandler(T t, String trace) {if (idx >= handlers.size()) {/*责任链结束*/return;}handlers.get(idx++).doHandler(t, this, trace);}}
5.4 测试验证:
public void method() {
AqrHandlerChain chain = new AqrHandlerChain();
chain.add(new Handler1());
chain.add(new Handler2());
chain.add(new Handler3());
List<Integer> lists = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
lists.add(ThreadLocalRandom.current().nextInt(0, 10));
}
System.out.println("method1 before --> " + JSON.toJSONString(lists));
chain.doHandler(lists, "trace");
System.out.println("method1 after --> " + JSON.toJSONString(lists));
}
6. 总结:
责任链模式很好的处理单一职责和开闭原则,简单了耦合也使对象关系更加清晰,而且外部的调用方并不需要关心责任链是如何进行处理的。但也需要是适当的场景才进行使用,避免造成性能以及编排混乱调试测试疏漏问题。(不知道请求被哪些责任链对象处理,不利于排错)


