职责链模式
欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。
# 简介
职责链模式(Chain of Responsibility Pattern),又叫责任链模式,为请求创建了一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦。
职责链模式通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求, 那么它会把相同的请求传给下一个接收者,依此类推。
- Handler:抽象的处理者,定义了一个处理请求的接口,同时包含另外 Handler。
- ConcreteHandler1 和 2:是具体的处理者,处理它自己负责的请求,可以访问它的后继者(setSuccessor),如果可以处理当前请求,则处理(handleRequest),否则就将该请求交个后继者去处理,从而形成一个职责链。
- Request:表示一个请求.
# 代码示例
编写程序完成学校 OA 系统的采购审批项目:
- 采购员采购教学器材
- 如果金额小于等于 5000,由教学主任审批。
- 如果金额小于等于 10000,由院长审批。
- 如果金额小于等于 30000,由副校长审批。
- 如果金额超过 30000 以上,由校长审批。
/**
* 定义一个采购请求
*/
@AllArgsConstructor
@Getter
public class PurchaseRequest {
private double amount; // 请求的金额。
private String itemName; //请求购入的器材
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
/**
* 抽象的审批者
*/
public abstract class Approver {
public Approver(String name) {
this.name = name;
}
protected String name;
protected Approver next;
// 设置下一个审批者
void setNext(Approver approver) {
this.next = approver;
}
abstract void handleRequest(PurchaseRequest request);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 教学主任
*/
public class TeachingDirector extends Approver {
public TeachingDirector() {
super("教学主任");
}
@Override
void handleRequest(PurchaseRequest request) {
if (request.getAmount() <= 5000) {
System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
} else if (next != null) {
next.handleRequest(request);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 院长
*/
public class Dean extends Approver {
public Dean() {
super("院长");
}
@Override
void handleRequest(PurchaseRequest request) {
if (request.getAmount() <= 10000) {
System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
} else if (next != null) {
next.handleRequest(request);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 副校长
*/
public class ViceChancellor extends Approver {
public ViceChancellor() {
super("副校长");
}
@Override
void handleRequest(PurchaseRequest request) {
if (request.getAmount() <= 30000) {
System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
} else if (next != null) {
next.handleRequest(request);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 校长
*/
public class Chancellor extends Approver {
public Chancellor() {
super("校长");
}
@Override
void handleRequest(PurchaseRequest request) {
System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 测试
*/
public class Client {
public static void main(String[] args) {
Approver teachingDirector = new TeachingDirector();
Approver dean = new Dean();
Approver viceChancellor = new ViceChancellor();
Approver chancellor = new Chancellor();
teachingDirector.setNext(dean);
dean.setNext(viceChancellor);
viceChancellor.setNext(chancellor);
teachingDirector.handleRequest(new PurchaseRequest(3000, "Projector"));
teachingDirector.handleRequest(new PurchaseRequest(8000, "Laptop"));
teachingDirector.handleRequest(new PurchaseRequest(15000, "Lab Equipment"));
teachingDirector.handleRequest(new PurchaseRequest(40000, "Server"));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 说明
职责链将请求和处理分开,实现解耦,提高系统的灵活性。
简化了对象,使对象不需要知道链的结构。
性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext () 方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能。
调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂。
最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假 / 加薪 等审批流程、Java Web 中 Tomcat 对 Encoding 的处理、拦截器等等。
# 职责链模式在 SpringMVC 框架应用
在 DispatcherServlet 类中的 doDispatch () 方法中
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
//...................
// 执行前置拦截方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
//...................
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
// 在前置拦截方法执行成功后执行,就和上面手写的setNext一样
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
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
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
上次更新: 2025/04/12, 05:37:39