责任链设计模式(Chain of Responsibility)的应用有:Java Web中的过滤器链、Struts2中的拦截器栈。java
先看一个问题:设计模式
给定一个字符串“被就业了:),敏感信息,<script>”,对其中的HTML标记和敏感词进行过滤或替换。
本文主要以该问题设计方法的演变来说解责任链设计模式。ide
第一种设计:没有任何设计模式post
设计了一个MsgProcessor类,完成字符串处理的主要工做。MainClass类是本设计中的测试类。测试
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
class
MainClass {
public
static
void
main(String[] args) {
//须要被过滤的语句
String msg =
"被就业了:),敏感信息,<script>"
;
//实例化处理类
MsgProcessor mp =
new
MsgProcessor(msg);
String r = mp.process();
System.out.println(r);
}
}
public
class
MsgProcessor {
private
String msg;
public
MsgProcessor(String msg){
this
.msg = msg;
}
public
String process(){
String r = msg;
//过滤msg中的HTML标记
r = r.replace(
"<"
,
"<"
).replace(
">"
,
">"
);
//过滤敏感词
r = r.replace(
"敏感"
,
""
).replace(
"被就业"
,
"就业"
);
return
r;
}
}
|
第二种设计:增长一个Filter接口this
在第一种设计中,对字符串的全部处理都放在MsgProcessor类中,扩展性极差。若是要过滤字符串中的笑脸(将”:)”替换成”^_^”),则须要改动MSgProcessor中的process方法。spa
01
02
03
04
05
06
07
08
09
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
|
public
interface
Filter {
String doFilter(String str);
}
public
class
HtmlFilter
implements
Filter {
public
String doFilter(String msg) {
String r = msg;
//过滤msg中的HTML标记
r = r.replace(
"<"
,
"<"
).replace(
">"
,
">"
);
return
r;
}
}
public
class
SensitiveFilter
implements
Filter {
public
String doFilter(String msg) {
String r = msg;
//过滤敏感词
r = r.replace(
"敏感"
,
""
).replace(
"被就业"
,
"就业"
);
return
r;
}
}
public
class
MsgProcessor {
private
String msg;
private
Filter[] filters = {
new
HtmlFilter(),
new
SensitiveFilter()};
public
MsgProcessor(String msg){
this
.msg = msg;
}
public
String process(){
String r = msg;
for
(Filter f : filters){
r = f.doFilter(r);
}
return
r;
}
}
|
此时,若是须要过滤字符串中的笑脸,只须要建立一个类FaceFilter实现Filter接口,并在MsgProcessor类中的filters字段中登记便可。设计
第三种设计:责任链模式(FilterChain)code
定义:将一个事件处理流程分派到一组执行对象上去,这一组执行对象造成一个链式结构,事件处理请求在这一组执行对象上进行传递。责任链模式的主要参与角色:orm
① 事件处理请求对象(Request)
② 执行对象(Handler)
01
02
03
04
05
06
07
08
09
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
|
public
class
FilterChain
implements
Filter {
public
List<Filter> filters=
new
ArrayList<Filter>();
public
FilterChain addFilter(Filter f){
filters.add(f);
return
this
;
}
public
String doFilter(String msg) {
//执行filters中的doFilter方法便可
String r = msg;
for
(Filter f : filters){
r = f.doFilter(r);
}
return
r;
}
}
public
class
MsgProcessor {
private
String msg;
private
FilterChain chain =
new
FilterChain();
public
MsgProcessor(String msg,Filter Chain){
this
.msg = msg;
this
.chain = chain;
}
public
String process(){
return
chain.doFilter(msg);
}
}
public
class
MainClass {
public
static
void
main(String[] args) {
//须要被过滤的语句
String msg =
"被就业了:),敏感信息,<script>"
;
//搞一个过过滤链
FilterChain chain =
new
FilterChain();
chain.addFilter(
new
HtmlFilter()).addFilter(
new
SensitiveFilter());
//实例化处理类
MsgProcessor mp =
new
MsgProcessor(msg,chain);
String r = mp.process();
System.out.println(r);
}
}
|
责任链模式增强版
上面的实现的过滤链能够用下图a)表示出来,整个过程只对msg过滤了一次。而JavaWeb中的过滤器链和Struts2中的拦截器栈执行的过程能够形象的表示为图b,☆很重要)。
下面用程序模拟JavaWeb中的过滤器,实现相似于对Request和Response的过滤。主要涉及的类以下所示:
01
02
03
04
05
06
07
08
09
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
|
public
interface
Filter {
void
doFilter(Request req,Response resp,FilterChain chain);
}
public
class
HtmlFilter
implements
Filter {
public
void
doFilter(Request req, Response resp, FilterChain chain) {
//过滤req.reqStr中的HTML标记
req.reqStr = req.reqStr.replace(
"<"
,
"<"
).replace(
">"
,
">"
);
req.reqStr +=
"---HtmlFilter()---"
;
chain.doFilter(req, resp);
resp.respStr +=
"---HtmlFilter()---"
;
}
}
public
class
SensitiveFilter
implements
Filter {
public
void
doFilter(Request req, Response resp, FilterChain chain) {
// 过滤req.reqStr中的敏感词
req.reqStr = req.reqStr.replace(
"敏感"
,
""
).replace(
"被就业"
,
"就业"
);
req.reqStr +=
"===SensitiveFilter"
;
chain.doFilter(req, resp);
resp.respStr +=
"===SensitiveFilter"
;
}
}
public
class
FilterChain{
private
List<Filter> filters =
new
ArrayList<Filter>();
//调用链上的过滤器时,记录过滤器的位置用
private
int
index =
0
;
public
FilterChain addFilter(Filter f){
filters.add(f);
return
this
;
}
public
void
doFilter(Request req, Response resp) {
if
(index == filters.size())
return
;
//获得当前过滤器
Filter f = filters.get(index);
index++;
f.doFilter(req, resp,
this
);
}
}
public
class
Request {
//在Request中只保持了一个reqStr字段记录对Request的操做
//为了方便模拟,没有将reqStr设置为private
String reqStr;
}
public
class
Response {
//在Response中只保持了一个respStr字段记录对Response的操做
//为了方便模拟,没有将respStr设置为private
String respStr;
}
package
org.flyne.fiter;
public
class
MainClass {
public
static
void
main(String[] args) {
// 须要被过滤的语句
String msg =
"被就业了:),敏感信息,<script>"
;
//建立Request、Response对象
Request req =
new
Request();
Response resp =
new
Response();
req.reqStr = msg;
resp.respStr =
"response"
;
//搞一个过滤链,链上有两个过滤器
FilterChain chain =
new
FilterChain();
chain.addFilter(
new
HtmlFilter())
.addFilter(
new
SensitiveFilter());
//开始过滤
chain.doFilter(req, resp);
System.out.println(req.reqStr);
System.out.println(resp.respStr);
}
}
|