:::info 责任链模式是一个相对比较简单的模式,它的名字已经非常好的暗示了其工作原理。每个处理器互相首尾连接在一起成为一条链,然后任务顺着这条链往下传,直到被某个处理器处理掉。 :::

定义

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

使用场景

一个请求需要被多个对象中的某一个处理,但是到底是哪个对象必须在运行时根据条件决定。

UML

责任链模式 - 图1

角色结构

  • Handler:所有处理器类的接口
  • ConcreteHandler :具体的处理器类,其实现Handler接口,有多少个处理器,就定义多少个这样的类

    优点

  • 是命令发出者与执行者解耦。

  • 一个命令可以被多个处理器执行,例如各种框架中的拦截器

    缺点

  • 不能保证请求一定被接收。

  • 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
  • 可能不容易观察运行时的特征,有碍于除错。

    业务场景

    二狗提出买一台Mac笔记本电脑。这花钱的事需要领导审批,而每个领导权限不一样,能够审批的最大金额有限制。二狗首先肯定是向自己的小组leader提出,但是由于金额太大,超出了他的审批权限。于是小组领导就去找自己的领导,部门经理,但是部门经理也权限不够,最后到了CFO那里…

王二狗遇到的情况就非常适合使用责任链模式。二狗这个预算申请的请求,事先不知道会由哪层领导处理,而各层领导的审批职责就好像铁链一样连接在一起,一个预算请求沿着这条链一直往上传… 让我们用代码来实现上面的场景吧。

代码示例

BudgetHandler 一个所有处理器都要实现的接口

  1. public interface BudgetHandler {
  2. /**
  3. * 设置下一个处理器
  4. */
  5. void setNextHandler(BudgetHandler nextHandler);
  6. /**
  7. * 负责处理请求
  8. */
  9. boolean handle(int amount);
  10. }

GroupLeader 小组领导类

  1. public class GroupLeader implements BudgetHandler {
  2. private BudgetHandler nextHandler;
  3. @Override
  4. public void setNextHandler(BudgetHandler nextHandler) {
  5. this.nextHandler = nextHandler;
  6. }
  7. /**
  8. * 小组领导最多可以批1000块以下的预算,再多了就批不了了。
  9. */
  10. @Override
  11. public boolean handle(int amount) {
  12. Objects.requireNonNull(nextHandler);
  13. if(amount<1000){
  14. System.out.println("小钱,批了!");
  15. return true;
  16. }
  17. System.out.println(String.format("%d超出GroupLeader权限,请更高级管理层批复",amount));
  18. return nextHandler.handle(amount);
  19. }
  20. }

Manager 部门经理类

  1. public class Manager implements BudgetHandler {
  2. private BudgetHandler nextHandler;
  3. @Override
  4. public void setNextHandler(BudgetHandler nextHandler) {
  5. this.nextHandler = nextHandler;
  6. }
  7. /**
  8. * 经理最多可以批5000块以下的预算
  9. */
  10. @Override
  11. public boolean handle(int amount) {
  12. Objects.requireNonNull(nextHandler);
  13. if (amount < 5000) {
  14. System.out.println("小于2000块,我这个经理可以决定:同意!");
  15. return true;
  16. }
  17. System.out.println(String.format("%d超出Manager权限,请更高级管理层批复", amount));
  18. return nextHandler.handle(amount);
  19. }
  20. }

CFO 首席财务执行官

  1. public class CFO implements BudgetHandler {
  2. private BudgetHandler nextHandler;
  3. @Override
  4. public void setNextHandler(BudgetHandler nextHandler) {
  5. this.nextHandler = nextHandler;
  6. }
  7. @Override
  8. public boolean handle(int amount) {
  9. if (amount < 50000) {
  10. System.out.println("CFO同意,希望你再接再厉,为公司做出更大的贡献。");
  11. return true;
  12. }
  13. if (nextHandler != null) {
  14. return nextHandler.handle(amount);
  15. }
  16. //已经没有更高级的管理层来处理了
  17. System.out.println(String.format("%d太多了,回去好好看看能不能缩减一下", amount));
  18. return false;
  19. }
  20. }

Client

每个处理器都建好了,那么怎么才能让他们连成链呢?
这里可以让客户端来组织,也可以初始化的时候每一级处理器都指定自己的下一级。

  1. public class Client {
  2. public static void main(String[] args) {
  3. GroupLeader leader = new GroupLeader();
  4. Manager manager = new Manager();
  5. CFO cfo = new CFO();
  6. leader.setNextHandler(manager);
  7. manager.setNextHandler(cfo);
  8. System.out.println(String.format("领导您好:由于开发需求,需要购买一台Mac笔记本电脑,预算为%d 望领导批准", 95000));
  9. if (leader.handle(25000)) {
  10. System.out.println("谢谢领导");
  11. } else {
  12. System.out.println("巧妇难为无米之炊,只能划船了...");
  13. }
  14. }
  15. }

输出

  1. 领导您好:由于开发需求,需要购买一台Mac笔记本电脑,预算为95000 望领导批准
  2. 25000超出GroupLeader权限,请更高级管理层批复
  3. 25000超出Manager权限,请更高级管理层批复
  4. CFO同意,希望你再接再厉,为公司做出更大的贡献。
  5. 谢谢领导