责任链设计模式(过滤器)

来源:互联网 发布:psv如何重新构筑数据库 编辑:程序博客网 时间:2024/04/28 23:46

责任链设计模式(过滤器、拦截器)


责任链设计模式(Chain of Responsibility)的应用有:Java Web中的过滤器链、Struts2中的拦截器栈。

先看一个问题:

给定一个字符串“被就业了:),敏感信息,<script>”,对其中的HTML标记和敏感词进行过滤或替换。
本文主要以该问题设计方法的演变来讲解责任链设计模式。

第一种设计:没有任何设计模式

设计了一个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
publicclass MainClass {
    publicstatic void main(String[] args) {
        //需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
 
        //实例化处理类
        MsgProcessor mp = newMsgProcessor(msg);
        String r = mp.process();
 
        System.out.println(r);
    }
 
}
 
publicclass MsgProcessor {
    privateString msg;
    publicMsgProcessor(String msg){
        this.msg = msg;
    }
 
    publicString process(){
        String r = msg;
        //过滤msg中的HTML标记
        r = r.replace("<","&lt;").replace(">","&gt;");
        //过滤敏感词
        r = r.replace("敏感","").replace("被就业","就业");
 
        returnr;
    }
}

第二种设计:增加一个Filter接口

在第一种设计中,对字符串的所有处理都放在MsgProcessor类中,扩展性极差。如果要过滤字符串中的笑脸(将”:)”替换成”^_^”),则需要改动MSgProcessor中的process方法。

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
publicinterface Filter {
    String doFilter(String str);
}
 
publicclass HtmlFilter implementsFilter {
    publicString doFilter(String msg) {
        String r = msg;
        //过滤msg中的HTML标记
        r = r.replace("<","&lt;").replace(">","&gt;");
 
        returnr;
    }
}
 
publicclass SensitiveFilter implementsFilter {
    publicString doFilter(String msg) {
        String r = msg;
        //过滤敏感词
        r = r.replace("敏感","").replace("被就业","就业");
 
        returnr;
    }
}
 
publicclass MsgProcessor {
    privateString msg;
    privateFilter[] filters = {newHtmlFilter(),newSensitiveFilter()};
 
    publicMsgProcessor(String msg){
        this.msg = msg;
    }
 
    publicString process(){
        String r = msg;
        for(Filter f : filters){
            r = f.doFilter(r);
        }
        returnr;
    }
}

此时,如果需要过滤字符串中的笑脸,只需要创建一个类FaceFilter实现Filter接口,并在MsgProcessor类中的filters字段中登记即可。

第三种设计:责任链模式(FilterChain)

定义:将一个事件处理流程分派到一组执行对象上去,这一组执行对象形成一个链式结构,事件处理请求在这一组执行对象上进行传递。责任链模式的主要参与角色:

① 事件处理请求对象(Request)

② 执行对象(Handler)

责任链设计模式(过滤器、拦截器)1838

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
publicclass FilterChain implementsFilter {
 
    publicList<Filter> filters= newArrayList<Filter>();
 
    publicFilterChain addFilter(Filter f){
        filters.add(f);
        returnthis;
    }
 
    publicString doFilter(String msg) {//执行filters中的doFilter方法即可
        String r = msg;
        for(Filter f : filters){
            r = f.doFilter(r);
        }
        returnr;
    }
}
 
publicclass MsgProcessor {
    privateString msg;
    privateFilterChain chain = newFilterChain();
 
    publicMsgProcessor(String msg,Filter Chain){
        this.msg = msg;
        this.chain = chain;
    }
 
    publicString process(){
        returnchain.doFilter(msg);
    }
}
 
publicclass MainClass {
    publicstatic void main(String[] args) {
        //需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
 
        //搞一个过过滤链
        FilterChain chain = newFilterChain();
        chain.addFilter(newHtmlFilter()).addFilter(newSensitiveFilter());
        //实例化处理类
        MsgProcessor mp = newMsgProcessor(msg,chain);
        String r = mp.process();
 
        System.out.println(r);
    }
}

责任链模式加强版
上面的实现的过滤链可以用下图a)表示出来,整个过程只对msg过滤了一次。而JavaWeb中的过滤器链和Struts2中的拦截器栈执行的过程可以形象的表示为图b,☆很重要)。

责任链设计模式(过滤器、拦截器)2890

下面用程序模拟JavaWeb中的过滤器,实现类似于对Request和Response的过滤。主要涉及的类如下所示:

责任链设计模式(过滤器、拦截器)2950

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
publicinterface Filter {
    voiddoFilter(Request req,Response resp,FilterChain chain);
}
 
publicclass HtmlFilter implementsFilter {
    publicvoid doFilter(Request req, Response resp, FilterChain chain) {
        //过滤req.reqStr中的HTML标记
        req.reqStr = req.reqStr.replace("<","&lt;").replace(">","&gt;");
        req.reqStr += "---HtmlFilter()---";
        chain.doFilter(req, resp);
        resp.respStr += "---HtmlFilter()---";
    }
}
 
publicclass SensitiveFilter implementsFilter {
    publicvoid 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";
    }
}
 
publicclass FilterChain{
    privateList<Filter> filters = newArrayList<Filter>();
    //调用链上的过滤器时,记录过滤器的位置用
    privateint index = 0;
 
    publicFilterChain addFilter(Filter f){
        filters.add(f);
        returnthis;
    }
 
    publicvoid doFilter(Request req, Response resp) {
        if(index == filters.size()) return;
        //得到当前过滤器
        Filter f = filters.get(index);
        index++;
 
        f.doFilter(req, resp, this);
    }
}
 
publicclass Request {
    //在Request中只保持了一个reqStr字段记录对Request的操作
    //为了方便模拟,没有将reqStr设置为private
    String reqStr;
}
 
publicclass Response {
    //在Response中只保持了一个respStr字段记录对Response的操作
    //为了方便模拟,没有将respStr设置为private
    String respStr;
}
packageorg.flyne.fiter;
 
publicclass MainClass {
    publicstatic void main(String[] args) {
        // 需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
 
        //创建Request、Response对象
        Request req = newRequest();
        Response resp = newResponse();
        req.reqStr = msg;
        resp.respStr = "response";
 
        //搞一个过滤链,链上有两个过滤器
        FilterChain chain = newFilterChain();
        chain.addFilter(newHtmlFilter())
            .addFilter(newSensitiveFilter());
 
        //开始过滤
        chain.doFilter(req, resp);
 
        System.out.println(req.reqStr);
        System.out.println(resp.respStr);
    }
}
0 0