chainOfResponsibility模式

情景引入

我们首先看看什么是推卸责任。假设现在我们要去公司领取资料。首先我们向公司前台打听要
去哪里领取资料,她告诉我们应该去“营业窗口”。然后等我们到了“营业窗口”后,又被告知应
该去“售后部门”。等我们好不容易赶到了“售后部门”,又被告知应该去“资料中心”,因此最后
我们又不得不赶往“资料中心”。像这样,在找到合适的办事人之前,我们被不断地踢给一个又一
个人,这就是“推卸责任”。

“推卸责任”听起来有些贬义的意思,但是有时候也确实存在需要“推卸责任”的情况。例如,
当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责
任。这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照它们在职责链上的顺序一个
一个地找出到底应该谁来负责处理

这种模式被称为Chain of Responsibility 模式。Responsibility有 “责任”的意思,在汉语中,
该模式称为“职责链”。总之,我们可以将它想象为推卸责任的结构,这有利于大家记住这种模式。
使用Chain of Responsibility模式可以弱化“请求方”和“处理方”之间的关联关系,让双方各
自都成为可独立复用的组件。此外,程序还可以应对其他需求,如根据情况不同,负责处理的对象
也会发生变化的这种需求。

当一个人被要求做什么事情时,如果他可以做就自己做,如果不能做就将“要求”转给另外一
个人。下一个人如果可以自己处理,就自己做;如果也不能自己处理,就再转给另外- …..这
就是Chain of Responsibility模式。

示例程序

功能描述

处理某个问题

类的一览表

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

UML

责任链模式

主要代码

Trouble 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Trouble {
private int number;//问题编号
public Trouble(int number) {//生成问题
this.number = number;
}

public int getNumber() {//获取问题编号
return number;
}

public String toString() {//代表问题的字符串
return " [Trouble" + number + "]";

}
}

Support 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public abstract class Support {
private String name;//解决问题的实例的名字
private Support next;//要推卸给的对象

public Support(String name) {//生成解决问题的实例
this.name = name;
}

public Support setNext(Support next) {//设置要推卸给的对象
this.next = next;
return next;
}

public final void support(Trouble trouble) { // 解决问题的步骤
if (resolve(trouble)) {
done(trouble);
} else if (next != null){
next.support(trouble);
}else{
fail(trouble);
}
}

public String toString() {
// 显示字符串
return "[" + name + "]";
}

protected abstract boolean resolve(Trouble trouble); // 解决问题的方法

protected void done(Trouble trouble) { // 解决
System.out.println(trouble +"is resolved by" + this + ".");
}

protected void fail(Trouble trouble) { // 未解决
System.out.println(trouble +"cannot be resolved.") ;
}
}

NoSupport 类

1
2
3
4
5
6
7
8
9
10
11
12
public class NoSupport extends Support{

public NoSupport(String name) {
super(name);
}

@Override
protected boolean resolve(Trouble trouble) {
return false;
}
}

LimitSupport 类

1
2
3
4
5
6
7
8
9
10
11
12
public class LimitSupport extends Support{
private int limit;
public LimitSupport(String name, int limit) {
super(name);
this.limit = limit;
}

@Override
protected boolean resolve(Trouble trouble) {
return trouble.getNumber() < limit;
}
}

OddSupport 类

1
2
3
4
5
6
7
8
9
10
11
public class OddSupport extends Support {

public OddSupport(String name) {
super(name);
}

@Override
protected boolean resolve(Trouble trouble) {
return trouble.getNumber() % 2 == 1;
}
}

SpecialSupport 类

1
2
3
4
5
6
7
8
9
10
11
12
public class SpecialSupport extends Support{
private int number;
public SpecialSupport(String name, int number) {
super(name);
this.number = number;
}

@Override
protected boolean resolve(Trouble trouble) {
return trouble.getNumber() == number;
}
}

Main 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
public static void main(String[] args) {
Support alice = new NoSupport("Alice");
Support bob = new LimitSupport("Bob", 100);
Support charlie = new SpecialSupport("Charlie", 429);
Support diana = new LimitSupport("Diana", 200);
Support elmo = new OddSupport("Elmo");
Support fred = new LimitSupport("Fred", 300);

//形成职责链
alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);

//制造各种问题
for (int i = 0; i < 500; i += 33) {
alice.support(new Trouble(i));

}
}
}

chainOfResponsibility模式
http://lhystutest.top/2022/11/04/设计模式/ChainOfResponsibility 模式/chainOfResponsibility/
作者
lhy
发布于
2022年11月4日
许可协议