Author:Gorit
Date:2021年11月8日
Refer:《图解设计模式》

14.1 Chain of Responsibility

“推卸责任” 这个词句听起来像是贬义词,但是有的时候确实需要“推卸责任”的情况。

举个例子:
当外部程序进行某项处理时,但内部程序暂时不知道由哪个对象负责处理,就需要推卸责任

这样的话:

我们可以考虑 将多个对象组成一条职责链,然后按照它们在职责链上的顺序一个一个地找出到底应该由谁来负责处理

“责任链模式”可以弱化 “请求方”和 “处理方”之间的关联关系,让双方都可以成为可独立复用的组件。此外,程序还可以处理其他需求,如根据情况不同,负责处理的对象也会发生变化的这种需求

换个比较形象的说法:

当一个人被要求做什么事情呢,如果他自己做就自己做,如果不能做就将“要求”转给另一个人。下一个人要么自己做,要么不能做也同样给下一个人处理,这就是 “责任链模式”

14.2 示例程序

类名 功能说明
Trouble 表示发生问题的类
Support 用来解决问题的抽象类
NotSupport 用来解决问题的具体类(永远“不处理问题”)
LimitSupport 用来解决问题的具体类(仅解决编号小于指定编号的问题)
OddSupport 用来解决问题的具体类(仅解决奇数编号问题)
SpecialSupport 用来解决问题的具体类(仅解决指定编号问题)
Main 制作 Support 的责任链,制作问题并测试程序的行为

Trouble 类

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021年11月9日
  5. * Border 和 Display 具有相同的属性和方法
  6. * display 代表被装饰物,也有可能是其他装饰物的边框
  7. **/
  8. public class Trouble {
  9. private int number; // 问题编号
  10. public Trouble(int number) { // 生成问题
  11. this.number = number;
  12. }
  13. public int getNumber() { // 获取问题编号
  14. return number;
  15. }
  16. public String toString() { // 代表问题字符串
  17. return "{Trouble " + number + "}";
  18. }
  19. }

Support 类

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/15
  5. * 用来解决问题的抽象类,它是职责链上的对象
  6. * next 字段中指定了要推卸给的对象,可以通过 setNext 方法设定该对象
  7. * resolve 该方法需要子类去实现的抽象方法。 resolve 返回 true 则表示被处理,反之
  8. * support 该方法会调用 resolve 方法,如果 resolve 方法返回 false,则 support 方法会将问题转交给下一个对象
  9. **/
  10. public abstract class Support {
  11. private String name; // 解决问题实例的名字
  12. private Support next; // 要推卸给的对象, 类似于链表结构
  13. public Support(String name) { // 生成问题的实例
  14. this.name = name;
  15. }
  16. public Support setNext(Support next) { // 设置要推卸给的对象, 链式调用
  17. this.next = next;
  18. return next;
  19. }
  20. public final void support(Trouble trouble) { // 解决问题的步骤
  21. if (resolve(trouble)) { // 属于 Template Method
  22. done(trouble);
  23. } else if (next != null) {
  24. next.support(trouble);
  25. } else {
  26. fail(trouble);
  27. }
  28. }
  29. @Override
  30. public String toString() { // 显示字符串
  31. return "{" + name +"}";
  32. }
  33. protected abstract boolean resolve(Trouble trouble); // 解决问题的方法
  34. protected void done(Trouble trouble) { // 解决
  35. System.out.println(trouble + " is resolved by " + this + ".");
  36. }
  37. protected void fail(Trouble trouble) {
  38. System.out.println(trouble + " cannot be resoled.");
  39. }
  40. }

NotSupport

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/15
  5. * Support 的子类
  6. * 永不解决的类
  7. **/
  8. public class NotSupport extends Support {
  9. public NotSupport(String name) {
  10. super(name);
  11. }
  12. protected boolean resolve(Trouble trouble) { // 永远不解决
  13. return false;
  14. }
  15. }

LimitSupport

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/15
  5. * 解决编号小于 limit 的问题
  6. * resolve 方法在判断编号小于 limit 值之后,只是返回 true,但实际上这里应该是解决问题的代码
  7. **/
  8. public class LimitSupport extends Support {
  9. private int limit;
  10. public LimitSupport(String name, int limit) {
  11. super(name);
  12. this.limit = limit;
  13. }
  14. protected boolean resolve(Trouble trouble) { // 解决问题的方法
  15. if (trouble.getNumber() < limit) {
  16. return true;
  17. } else {
  18. return false;
  19. }
  20. }
  21. }

OddSupport

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/15
  5. * 解决奇数编号问题
  6. **/
  7. public class OddSupport extends Support {
  8. public OddSupport(String name) {
  9. super(name);
  10. }
  11. protected boolean resolve(Trouble trouble) {
  12. if (trouble.getNumber() % 2 == 0) {
  13. return true;
  14. }
  15. return false;
  16. }
  17. }

SpecialSupport

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/15
  5. * 只解决指定编号问题
  6. **/
  7. public class SpecilSupport extends Support {
  8. private int number;
  9. public SpecilSupport(String name, int number) { // 只能解决指定编号的问题
  10. super(name);
  11. this.number = number;
  12. }
  13. protected boolean resolve(Trouble trouble) {
  14. if (trouble.getNumber() == number) {
  15. return true;
  16. }
  17. return false;
  18. }
  19. }

Main

  1. package Responsibility;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/15
  5. **/
  6. public class Main {
  7. public static void main(String[] args) {
  8. Support alice = new NotSupport("Alice");
  9. Support bob = new LimitSupport("Bob", 100);
  10. Support charlie = new SpecilSupport("Charlie", 429);
  11. Support diana = new LimitSupport("Diana", 200);
  12. Support elmo = new OddSupport("elmo");
  13. Support fred = new LimitSupport("fred", 300);
  14. // 形成责任链
  15. alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
  16. for (int i = 0; i < 500; i += 33) {
  17. alice.support(new Trouble(i));
  18. }
  19. }
  20. }

14.3 Chain of Responsibility 模式中登场的角色

一、Handler(处理者)

Handler 角色定义了处理请求的接口(API)。Handler 角色知道“下一个处理者”是谁,若自己无法处理请求,则将请求转给“下一个请求者”。然后依次类推,在本节中,Support 类扮演此角色。负责请求的是 Support 方法

二、ConcreateHandler(具体的处理者)

示例程序中:

  • NotSupport
  • LimitSupport
  • OddSupport
  • SpecialSupport

扮演此角色

三、Client 角色(请求者)

Client 角色是向第一个 ConcreateHandler 角色发送请求的角色。示例程序中由 Main 扮演此角色