【Java设计模式】:行为型模式—责任链模式

1. 责任链模式定义

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。Tomcat中的Filter就是使用了责任链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现javax.servlet.Filter接口。

2. 具体实例

我们有一个字符串String msg = ":):,<script>,敏感,被就业,网络授课";我们希望应用以下三个规则对字符串进行过滤和谐处理:

  1. 将字符串中出现的"<>“符号替换成”[]"
  2. 处理字符串中的敏感信息,将被就业和谐成就业
  3. 将字符串中出现的":):"转换成"^V^"

字符串会依次运用这三条规则,对字符串进行处理,每个规则都有自己需要完成的责任和任务。

第一步:定义封装请求的类Request和封装处理结果响应的类Response

//封装请求的类Request
public class Request {
    String requestStr;

    public String getRequest() {
        return requestStr;
    }

    public void setRequest(String request) {
        this.requestStr = request;
    }
    
}
//封装响应信息的类Response
public class Response {
    String responseStr;

    public String getResponse() {
        return responseStr;
    }

    public void setResponse(String response) {
        this.responseStr = response;
    }
    
}

第二步:定义具有过滤功能的接口Filter,具体的过滤规则需要实现该接口

/*
 * 定义接口Filter,具体的过滤规则需要实现这个接口,最后一个参数添加的意义是我们在Main函数中:
 * fc.doFilter(request, response,fc);执行这一步的时候可以按照规则链条一次使用三个过滤规则对字符串进行处理
 * 因为
 * 
 */
public interface Filter {
    void doFilter(Request request,Response response,FilterChain chain);
}

第三步:定义具体的过滤处理规则

规则一

package com.bjsxt.dp.filter;

//处理字符串中的HTML标记
public class HTMLFilter implements Filter {

    public void doFilter(Request request, Response response,FilterChain chain) {
        //将字符串中出现的"<>"符号替换成"[]"
        request.requestStr=request.requestStr
                .replace('<', '[').replace('>', ']')+
                //后面添加的是便于我们观察代码执行步骤的字符串
                "----HTMLFilter()";
        chain.doFilter(request, response,chain);
        response.responseStr+="---HTMLFilter()";
    }

}

规则二

package com.bjsxt.dp.filter;

//定义的过滤敏感字眼的过滤规则
public class SensitiveFilter implements Filter{

    public void doFilter(Request request, Response response,FilterChain chain) {
        //处理字符串中的敏感信息,将被就业和谐成就业
        request.requestStr=request.requestStr
                .replace("被就业", "就业").replace("敏感", "")+
                //后面添加的是便于我们观察代码执行步骤的字符串
                " ---sensitiveFilter()";
        chain.doFilter(request, response,chain);
        response.responseStr+="---sensitiveFilter()";
    }

}

规则三

package com.bjsxt.dp.filter;

//定义FaceFilter
public class FaceFilter implements Filter {

    public void doFilter(Request request, Response response, FilterChain chain) {

        //将字符串中出现的":):"转换成"^V^";
        request.requestStr = request.requestStr.replace(":):", "^V^")
                //后面添加的是便于我们观察代码执行步骤的字符串
                + "----FaceFilter()";
        chain.doFilter(request, response, chain);
        response.responseStr += "---FaceFilter()";
    }

}

第四步:定义责任链FilterChain

package com.bjsxt.dp.filter;

import java.util.ArrayList;
import java.util.List;

//过滤链条
public class FilterChain implements Filter{
    //用List集合来存储过滤规则
    List<Filter> filters = new ArrayList<Filter>();
    //用于标记规则的引用顺序
    int index=0;
    //往规则链条中添加规则
    public FilterChain addFilter(Filter f) {
        filters.add(f);
        //代码的设计技巧:Chain链添加过滤规则结束后返回添加后的Chain,方便我们下面doFilter函数的操作
        return this;
    }
    public void doFilter(Request request,Response response,FilterChain chain){
        //index初始化为0,filters.size()为3,不会执行return操作
        if(index==filters.size()){
            return;
        }
        //每添加一个过滤规则,index自增1
        Filter f=filters.get(index);
        index++;
        //根据索引值获取对应的规律规则对字符串进行处理
        f.doFilter(request, response, chain);
    }
}

第五步:测试一下我们的代码

package com.bjsxt.dp.filter;

/*
 * 责任链模式:
 * 数据消息在进入数据库之前,要被多种过滤规则进行处理,多种规则形成一种链,依次处理
 * 给定的数据消息
 */
public class Main {
    public static void main(String args[]) {
        //设定过滤规则,对msg字符串进行过滤处理
        String msg = ":):,<script>,敏感,被就业,网络授课";
        //过滤请求
        Request request=new Request();
        //set方法,将待处理字符串传递进去
        request.setRequest(msg);
        //处理过程结束,给出的响应
        Response response=new Response();
        //设置响应信息
        response.setResponse("response:");
        //FilterChain,过滤规则形成的拦截链条
        FilterChain fc=new FilterChain();
        //规则链条添加过滤规则,采用的是链式调用
        fc.addFilter(new HTMLFilter())
        .addFilter(new SensitiveFilter())
        .addFilter(new FaceFilter());
        //按照FilterChain的规则顺序,依次应用过滤规则
        fc.doFilter(request, response,fc);
        //打印请求信息
        System.out.println(request.getRequest());
        //打印响应信息
        System.out.println(response.getResponse());
        /*
         * 处理器对数据进行处理
         * --|----|---数据--|-----|--- 
         * 规则1      规则2                 规则3       规则4
         */
    }
}

运行结果:

^V^,[script],,就业,网络授课----HTMLFilter() ---sensitiveFilter()----FaceFilter()
response:---FaceFilter()---sensitiveFilter()---HTMLFilter()

运行过程如下:
在这里插入图片描述

3. 责任链模式的好处

过滤链的好处是,发出请求的客户端并不知道链上的哪一个过滤器将处理这个请求,这使得系统可以在不影响客户端的情况下 动态地重新组织链和分配责任,并且在执行过程中的任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容,这显然可以看作是 非纯责任链模式 的一种典型实现。

参考:

  1. https://www.cnblogs.com/ysw-go/p/5432921.html
  2. https://blog.csdn.net/uftjtt/article/details/80116807
  3. https://www.cnblogs.com/coshaho/p/6815490.html
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页