责任链模式(Chain of Responsibility)

客户端对象发起请求,请求由下一个对象往下传递,直到被处某一个对象处理了此请求。客户端对象不需要知道是哪个节点进行了处理。这就可以在不景响客户端对象的情况下动态地重新组织和分配责任。

白话:一条对象链调下去。
A->B->C->D
A 持有 B 的引用,B 持有 C 的引用,C 持有 D 的引用。
开始执行A的逻辑,A能处理就处理了,不能处理就拿着B的引用,调用B去处理。整个逻辑就是这样一直往下去推。

1.角色
抽象处理者(Hand):
处理请求的接口。所有处理者都实现这个接口。
接口可以定义出一个方法以设定和返回对下家的引用。通常由抽象类或接口实现。
具体处理者(ConcreteHandler)
具体处理者接到请求后可以选择将请求处理掉,或者将请求传给下家。
因为具体处理都持有下家的引用。

2.处理顺序
可线性,可循环。

1.手动构建责任链

这种方式,我觉得挺low的,需要手动构建,不过在刚学习的时候,还是可以帮助理解。
需要角色:

  1. Handler
  2. Handler实现类
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// 抽象处理器类
abstract class Handler {
private Handler nextHandler; // 下一个处理器

public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}

public void handleRequest(String request) {
if (canHandle(request)) {
processRequest(request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("No handler available for the request: " + request);
}
}

protected abstract boolean canHandle(String request);

protected abstract void processRequest(String request);
}

// 具体处理器类A
class ConcreteHandlerA extends Handler {
protected boolean canHandle(String request) {
// 判断是否能处理请求的逻辑
return request.equals("A");
}

protected void processRequest(String request) {
// 处理请求的逻辑
System.out.println("ConcreteHandlerA is handling the request: " + request);
}
}

// 具体处理器类B
class ConcreteHandlerB extends Handler {
protected boolean canHandle(String request) {
// 判断是否能处理请求的逻辑
return request.equals("B");
}

protected void processRequest(String request) {
// 处理请求的逻辑
System.out.println("ConcreteHandlerB is handling the request: " + request);
}
}

// 具体处理器类C
class ConcreteHandlerC extends Handler {
protected boolean canHandle(String request) {
// 判断是否能处理请求的逻辑
return request.equals("C");
}

protected void processRequest(String request) {
// 处理请求的逻辑
System.out.println("ConcreteHandlerC is handling the request: " + request);
}
}

// 示例用法
public class Test {
public static void main(String[] args) {
// 创建处理器实例
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();

// 设置处理器的下一个处理器
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);

// 发送请求
handlerA.handleRequest("A"); // ConcreteHandlerA 处理请求
handlerA.handleRequest("B"); // ConcreteHandlerB 处理请求
handlerA.handleRequest("C"); // ConcreteHandlerC 处理请求
handlerA.handleRequest("D"); // 没有处理器能处理该请求
}
}

2.遍历方式访问责任链

这种方式的优点就是可以动态的添加责任链类,将需要的继承接口即可成为责任链的一环。
新增或移动都不需要额外的改代码,耦合性很低。

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
遍历方式模式

// 处理器接口
interface Handler {
boolean canHandle(String request);
void processRequest(String request);
}


import java.util.LinkedList;
import java.util.List;

// 处理器实现类
class HandlerImpl implements Handler {
private final List<Handler> handlers;

public HandlerImpl() {
handlers = new LinkedList<>();
}

public void addHandler(Handler handler) {
handlers.add(handler);
}

public void handleRequest(String request) {
for (Handler handler : handlers) {
if (handler.canHandle(request)) {
handler.processRequest(request);
return;
}
}
System.out.println("No handler available for the request: " + request);
}

public boolean canHandle(String request) {
return false; // 不需要实现
}

public void processRequest(String request) {
// 不需要实现
}
}


// 具体处理器类A
class ConcreteHandlerA implements Handler {
public boolean canHandle(String request) {
return request.equals("A");
}

public void processRequest(String request) {
System.out.println("ConcreteHandlerA is handling the request: " + request);
}
}

// 具体处理器类B
class ConcreteHandlerB implements Handler {
public boolean canHandle(String request) {
return request.equals("B");
}

public void processRequest(String request) {
System.out.println("ConcreteHandlerB is handling the request: " + request);
}
}

// 具体处理器类C
class ConcreteHandlerC implements Handler {
public boolean canHandle(String request) {
return request.equals("C");
}

public void processRequest(String request) {
System.out.println("ConcreteHandlerC is handling the request: " + request);
}
}



public class Test {
public static void main(String[] args) {
// 创建处理器实例
HandlerImpl handlerChain = new HandlerImpl();

// 添加处理器到处理器链
handlerChain.addHandler(new ConcreteHandlerA());
handlerChain.addHandler(new ConcreteHandlerB());
handlerChain.addHandler(new ConcreteHandlerC());

// 发送请求
handlerChain.handleRequest("A"); // ConcreteHandlerA 处理请求
handlerChain.handleRequest("B"); // ConcreteHandlerB 处理请求
handlerChain.handleRequest("C"); // ConcreteHandlerC 处理请求
handlerChain.handleRequest("D"); // 没有处理器能处理该请求
}
}

3.基于顺序的责任链

这里需要注意的是 getPriority 方法,这个用来指定优先及。

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
39
40
41
42
43
44
45
46
47
48
interface Handler {
boolean canHandle(String request);
void processRequest(String request);
int getPriority();
}


class ConcreteHandlerA implements Handler {
public boolean canHandle(String request) {
return request.equals("A");
}

public void processRequest(String request) {
System.out.println("ConcreteHandlerA is handling the request: " + request);
}

public int getPriority() {
return 1;
}
}

class ConcreteHandlerB implements Handler {
public boolean canHandle(String request) {
return request.equals("B");
}

public void processRequest(String request) {
System.out.println("ConcreteHandlerB is handling the request: " + request);
}

public int getPriority() {
return 2;
}
}

class ConcreteHandlerC implements Handler {
public boolean canHandle(String request) {
return request.equals("C");
}

public void processRequest(String request) {
System.out.println("ConcreteHandlerC is handling the request: " + request);
}

public int getPriority() {
return 3;
}
}

构建顺序

下面的代码中,只有一段代码需要注意,放到最后解释

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
import java.util.PriorityQueue;
import java.util.Queue;

class HandlerImpl implements Handler {
private final Queue<Handler> handlers;

public HandlerImpl() {
handlers = new PriorityQueue<>((h1, h2) -> h2.getPriority() - h1.getPriority());
}

public void addHandler(Handler handler) {
handlers.add(handler);
}

public void handleRequest(String request) {
for (Handler handler : handlers) {
if (handler.canHandle(request)) {
handler.processRequest(request);
return;
}
}
System.out.println("No handler available for the request: " + request);
}

// 这里还可以加上逻辑控制,如果处理结果不是预期结果,可以不往下执行
public boolean canHandle(String request) {
return false; // 不需要实现
}

public void processRequest(String request) {
// 不需要实现
}

public int getPriority() {
return 0; // 不需要实现
}
}

(h1, h2) -> h2.getPriority() - h1.getPriority() 是一个lambda表达式,它定义了一个比较器。比较器用于确定元素在队列中的顺序。
在这个比较器中,h1 和 h2 是两个要进行比较的元素。getPriority() 是处理器接口中定义的方法,用于获取处理器的优先级。
比较器的逻辑是将两个元素的优先级进行比较,如果 h2 的优先级大于 h1 的优先级,返回一个正数;如果 h2 的优先级小于 h1 的优先级,返回一个负数;如果两个元素的优先级相同,返回0。
根据这个比较器的逻辑,优先队列会根据处理器的优先级进行排序,优先级较高的处理器将排在队列的前面。
这样,在调用 handlers.add(handler) 将处理器添加到优先队列时,队列会根据处理器的优先级自动进行排序。

总结

实际应用的中比如filter就是一种典型的责任链,而在实际业务开发中,责任链非常常用,将业务逻辑组织成一个责任链条,传递每一环业务的结果。很有帮助,实际中使用Spring来组装的场景比较多。非Spring的话,也基本就是第三种方式就够用了。