设计模式(11)——责任链模式

本文介绍责任链模式的概念和应用。

基本思想和原则

使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

动机

如果一个处理过程中,多个处理环节的优先级有顺序关系(甚至我们希望可以随意组合这些环节以构成不同的处理方式),而且具体由哪个环节来处理依赖于一些条件,我们可以将其抽象为责任链模式。

实现

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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
public abstract class Handler {
private Handler nextHandler;

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

public final Response handleMessage(Request request) {
Response response = null;
if (this.getHanlerLevel().equals(request.getLevel())) {
response = this.makeResponse(request);
} else {
if (this.nextHandler != null) {
System.out.println("pass to next handler...");
response = this.nextHandler.handleMessage(request);
}
}
return response;
}

protected abstract Level getHanlerLevel();
protected abstract Response makeResponse(Request request);
}

public class BranchManager extends Handler {
@Override
protected Level getHanlerLevel() {
return new Level(1);
}

@Override
protected Response makeResponse(Request request) {
return new Response("BranchManager: OK");
}
}

public class Director extends Handler {
@Override
protected Level getHanlerLevel() {
return new Level(2);
}

@Override
protected Response makeResponse(Request request) {
return new Response("Director: OK");
}
}

public class GeneralManager extends Handler {
@Override
protected Level getHanlerLevel() {
return new Level(3);
}

@Override
protected Response makeResponse(Request request) {
return new Response("GeneralManager: OK");
}
}

public class Level {
private int level;

public Level(int level) {
this.level = level;
}

public int getLevel() {
return level;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof Level) {
Level level = (Level) obj;
return this.level == level.level;
}
return false;
}
}

public class Request {
private Level level;

public Request(Level level) {
this.level = level;
}

public Level getLevel() {
return this.level;
}
}

public class Response {
private String content;

public Response(String content) {
this.content = content;
}

public String getContent() {
return content;
}
}

public class Test {
public static void main(String[] args) {
Handler branchManager = new BranchManager();
Handler director = new Director();
Handler generalManager = new GeneralManager();

branchManager.setNextHandler(director);
director.setNextHandler(generalManager);

Request request1 = new Request(new Level(1));
Response response1 = branchManager.handleMessage(request1);
System.out.println(response1.getContent());

Request request2 = new Request(new Level(2));
Response response2 = branchManager.handleMessage(request2);
System.out.println(response2.getContent());

Request request3 = new Request(new Level(3));
Response response3 = branchManager.handleMessage(request3);
System.out.println(response3.getContent());

}
}

输出如下:

1
2
3
4
5
6
BranchManager: OK
pass to next handler...
Director: OK
pass to next handler...
pass to next handler...
GeneralManager: OK

上面的代码模拟了一个公司的审批流程,员工发起一个请求,请求有三种等级,等级一只需要部门经理审批,等级二需要总监审批,等级三需要总经理审批,责任链的形式为:部门经理->总监->总经理。我们在场景中分别模拟了这三种等级。

需要注意的是,我们在场景类中设置了责任链中各个节点的关系:

1
2
branchManager.setNextHandler(director);
director.setNextHandler(generalManager);

在责任链模式中,最核心的概念是责任的传递,链上的每个节点在接收到一个请求时都需要做如下判断:如果该请求的等级是自己可以处理的就直接处理并返回一个响应,否则就传递给链上的下一个节点处理。之后如果需要在链上增加新的处理节点也非常简单,只需要增加一个处理节点的类,然后更新链中节点关系即可。

优点

责任链模式对调用方屏蔽了请求处理的细节,调用方不需要去了解具体是哪个类在处理请求,也不需要了解是这么处理的,只要将请求传给链中的第一个对象,就会获得一个返回结果。这有利于类间解耦。

缺点

责任链的缺点是有可能建立一条很长的处理链导致系统性能受到影响,这在实际设计过程中要注意。