1. 概念:

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

2. 一坨代码实现:

责任链模式 - 图3
这里从上到下分别判断了在指定时间范围内由不同的人员进行审批,这样实现起来比较简单,但这样的实现就很难进行扩展。

3. 责任链模式重构代码:

下图是责任链结构的核心部分, 实现了统一抽象类的不同规则, 再进行编排, 就形成了一条链路.
责任链模式 - 图4

3.1 链路抽象类定义:

  1. public abstract class ApprovalLink {
  2. protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 时间格式化
  3. protected String levelUserName; // 级别人员姓名
  4. private ApprovalLink next; // 责任链
  5. public ApprovalLink(String levelUserName) {
  6. this.levelUserName = levelUserName;
  7. }
  8. public ApprovalLink next() {
  9. return next;
  10. }
  11. public ApprovalLink appendNext(ApprovalLink next) {
  12. this.next = next;
  13. return this;
  14. }
  15. /*抽象审批方法*/
  16. public abstract void approval(String publishId, Date publishDate);
  17. /**
  18. * 链路入口
  19. *
  20. * @param publishId
  21. * @param publishDate
  22. * @return
  23. */
  24. public Result run(String publishId, Date publishDate) {
  25. try {
  26. approval(publishId, publishDate);
  27. ApprovalLink link = this;
  28. while (true) {
  29. link = link.next();
  30. if (link == null) {
  31. return new Result("200", "单号:", publishId, " 状态:审批完成");
  32. }
  33. link.approval(publishId, publishDate);
  34. }
  35. } catch (RuntimeException e) {
  36. return new Result("500", "单号:", publishId, " 状态: " + e.getMessage());
  37. }
  38. }
  39. }

3.2 审批实现类:

  1. // 三级审批
  2. public class FirstApprovalLink extends ApprovalLink {
  3. public FirstApprovalLink(String levelUserName) {
  4. super(levelUserName);
  5. }
  6. @Override
  7. public void approval(String publishId, Date publishDate) {
  8. // 三级审批人
  9. log.info("三级审批开始...并自动通过 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);
  10. }
  11. }
  12. // 二级审批
  13. public class SecondAuthLink extends ApprovalLink {
  14. private Date beginDate = f.parse("2021-04-01 00:00:00");
  15. private Date endDate = f.parse("2021-04-29 23:59:59");
  16. public SecondAuthLink(String levelUserName) throws ParseException {
  17. super(levelUserName);
  18. }
  19. @Override
  20. public void approval(String publishId, Date publishDate) {
  21. log.info("二级审批开始... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);
  22. if (publishDate.before(beginDate) || publishDate.after(endDate)) {
  23. log.info("二级审批通过... 发布单id:{},审批人:系统自动通过,审批时间:{};", publishId, publishDate);
  24. return;
  25. }
  26. if (ThreadLocalRandom.current().nextInt(0, 2) == 0) {
  27. log.info("二级审批未通过");
  28. throw new RuntimeException("二级审批未通过");
  29. }
  30. log.info("二级审批通过... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);
  31. }
  32. }
  33. // 一级审批
  34. public class ThirdAuthLink extends ApprovalLink {
  35. private Date beginDate = f.parse("2021-04-20 00:00:00");
  36. private Date endDate = f.parse("2021-04-22 23:59:59");
  37. public ThirdAuthLink(String levelUserName) throws ParseException {
  38. super(levelUserName);
  39. }
  40. @Override
  41. public void approval(String publishId, Date publishDate) {
  42. log.info("一级审批开始... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);
  43. if (publishDate.before(beginDate) || publishDate.after(endDate)) {
  44. log.info("一级审批通过... 发布单id:{},审批人:系统自动通过,审批时间:{};", publishId, publishDate);
  45. return;
  46. }
  47. if (ThreadLocalRandom.current().nextInt(0, 2) == 0) {
  48. log.info("一级审批未通过");
  49. throw new RuntimeException("一级审批未通过");
  50. }
  51. log.info("一级审批通过... 发布单id:{},审批人:{},审批时间:{};", publishId, levelUserName, publishDate);
  52. }
  53. }

3.3 测试验证:

  1. public void method() throws ParseException {
  2. ApprovalLink first = new FirstApprovalLink("组长");
  3. ApprovalLink second = new SecondAuthLink("总监");
  4. ApprovalLink third = new ThirdAuthLink("CTO");
  5. second.appendNext(third);
  6. first.appendNext(second);
  7. log.info("测试结果:{}", JSON.toJSONString(first.run("202104251730010001", new Date())));
  8. }

4. 项目中使用:

责任链模式 - 图5
责任链模式 - 图6
责任链模式 - 图7

5. Servlet中的Filter

filter也是典型的责任链模式,是基于回调函数执行的, 在每一个过滤器执行完业务逻辑之后,都会调用FilterChain类, 而FilterChain中也会显示的调用下一个过滤器。
责任链模式 - 图8

5.1 处理器接口定义:

  1. public interface AqrHandler<T> {
  2. void doHandler(T t, AqrHandlerChain chain, String trace);
  3. }

5.2 处理器实现类:

  1. public class Handler1 implements AqrHandler<List<Integer>> {
  2. @Override
  3. public void doHandler(List<Integer> integers, AqrHandlerChain chain, String trace) {
  4. Iterator<Integer> iterator = integers.iterator();
  5. while (iterator.hasNext()) {
  6. Integer next = iterator.next();
  7. if (next == 3) {
  8. iterator.remove();
  9. }
  10. }
  11. chain.doHandler(integers,trace);
  12. }
  13. }
  14. public class Handler2 implements AqrHandler<List<Integer>> {
  15. @Override
  16. public void doHandler(List<Integer> integers, AqrHandlerChain chain, String trace) {
  17. Iterator<Integer> iterator = integers.iterator();
  18. while (iterator.hasNext()) {
  19. Integer next = iterator.next();
  20. if (next == 6) {
  21. iterator.remove();
  22. }
  23. }
  24. chain.doHandler(integers,trace);
  25. }
  26. }
  27. public class Handler3 implements AqrHandler<List<Integer>> {
  28. @Override
  29. public void doHandler(List<Integer> integers, AqrHandlerChain chain, String trace) {
  30. Iterator<Integer> iterator = integers.iterator();
  31. while (iterator.hasNext()) {
  32. Integer next = iterator.next();
  33. if (next == 9) {
  34. iterator.remove();
  35. }
  36. }
  37. chain.doHandler(integers,trace);
  38. }
  39. }

5.3 责任链:

  1. public class AqrHandlerChain<T> {
  2. /**
  3. * 处理器集合
  4. */
  5. private List<AqrHandler> handlers = new ArrayList<>();
  6. /**
  7. * 处理器索引下标
  8. */
  9. private int idx = 0;
  10. /**
  11. * 添加处理器
  12. *
  13. * @param filter
  14. */
  15. public void add(AqrHandler filter) {
  16. handlers.add(filter);
  17. }
  18. public void doHandler(T t, String trace) {
  19. if (idx >= handlers.size()) {
  20. /*责任链结束*/
  21. return;
  22. }
  23. handlers.get(idx++).doHandler(t, this, trace);
  24. }
  25. }

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. 总结:

责任链模式很好的处理单一职责和开闭原则,简单了耦合也使对象关系更加清晰,而且外部的调用方并不需要关心责任链是如何进行处理的。但也需要是适当的场景才进行使用,避免造成性能以及编排混乱调试测试疏漏问题。(不知道请求被哪些责任链对象处理,不利于排错)