# 责任链模式ChainOfResponsibility
阅读量 loading
# 一、概念
# 1、定义
为请求创建一个接收此次请求对象的链。
# 2、类型
行为型
# 3、适用场景
一个请求的处理需要多个对象当中的一个或几个协作处理
# 4、优点
- 请求的发送者和接受者(请求的处理者)解耦
- 责任链可以动态组合
# 5、缺点
- 责任链太长或者处理时间过长,影响性能
- 责任链有可能过多
# 6、相关设计模式
- 责任链模式和状态模式
责任链模式中各个对象并不指定下一个处理的对象是谁,只有在客户端设计链条中的顺序以及元素,直到被某个责任链条处理或者整个链条结束。状态模式是让每个状态对象知道自己下一个处理的对象是谁。
# 二、应用
现在模拟课程发布的一个应用场景。首先是课程类:
public class Course {
private String name;
private String article;
private String video;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
}
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
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
审批者类:
public abstract class Approver {
protected Approver approver;
public void setNextApprover(Approver approver) {
this.approver = approver;
}
public abstract void deploy(Course course);
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
再创建一个手机的审批者和视频的审批者:
public class ArticleApprover extends Approver {
@Override
public void deploy(Course course) {
if (StringUtils.isNotBlank(course.getArticle())) {
System.out.println(course.getName() + "含有手记,批准");
if (approver != null) {
approver.deploy(course);
}
} else {
System.out.println(course.getName() + "不含有手记,不批准,流程结束");
return;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class VideoApprover extends Approver {
@Override
public void deploy(Course course) {
if (StringUtils.isNotBlank(course.getArticle())) {
System.out.println(course.getVideo() + "含有视频,批准");
if (approver != null) {
approver.deploy(course);
}
} else {
System.out.println(course.getVideo() + "不含有视频,不批准,流程结束");
return;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
类图:
测试类:
public class Test {
public static void main(String[] args) {
Approver articleApprover = new ArticleApprover();
Approver videoApprover = new VideoApprover();
Course course = new Course();
course.setName("设计模式");
course.setArticle("设计模式手机");
course.setVideo("设计模式视频");
articleApprover.setNextApprover(videoApprover);
articleApprover.deploy(course);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
执行结果:
设计模式含有手记,批准
设计模式视频含有视频,批准
1
2
2
# 三、源码中的应用
# Filter
javax.servlet
包下的 Filter
接口有一个 doFilter()
方法:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
1
2
2
其中的 FilterChain
参数:
public interface FilterChain {
/**
* Causes the next filter in the chain to be invoked, or if the calling
* filter is the last filter in the chain, causes the resource at the end of
* the chain to be invoked.
*
* @param request
* the request to pass along the chain.
* @param response
* the response to pass along the chain.
*
* @since 2.3
*/
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FilterChain
中有很多 Filter
,这些 Filter
按照一定逻辑顺序组装成一个链条。这就是责任链模式,具体的某一个 Filter
就是链条中的一个元素。实现 FilterChain
的接口 MockFilterChain
,它是为了方便 Spring
测试或者 Mock
使用的。Filter
的实现就比较多了,例如:LoggerContextFilter
,它的 doFilter()
方法:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
ContextSelector selector = ContextSelectorStaticBinder.getSingleton().getContextSelector();
ContextJNDISelector sel = null;
if (selector instanceof ContextJNDISelector) {
sel = (ContextJNDISelector)selector;
sel.setLocalContext(lc);
}
try {
chain.doFilter(request, response);
} finally {
if (sel != null) {
sel.removeLocalContext();
}
}
}
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