设计模式之责任链(ChainOfResponsibility)

#责任链(ChainOfResponsibility)java

对于设计模式的学习,必定要动手,并且要屡次练习,而后慢慢消化和理解,才能明白其精髓。可是,设计模式只是在特殊情景下的特殊解决方案,不要滥用,不要为了使用设计模式而硬生生得去使用。设计模式的使用应该天然、优雅!web

问题

public class TestMain {
public static void main(String[] args) {
    String str = "你好:),这句话中有敏感词汇,须要处理。<script>,敏感!";
    MsgProcessor pro = new MsgProcessor();
    pro.setMsg(str);
    str = pro.processor();---
    System.out.println(str);
}
}

另外一个类:编程

public class MsgProcessor {
private String msg;
public String getMsg() {
    return msg;
}
public void setMsg(String msg) {
    this.msg = msg;
}

public String processor(){
    String content = "";
    if(null != msg && !("").equals(msg.trim())){
        content = msg.replace("<", "{")
        .replace(">", "}");
        
        content = content.replace("敏感", "");
        content = content.replace(":)", "^V^");
    }
    return content;
}  
}

上面的代码完成了对一个字符串的简单过滤,可是很明显这样的代码很很差。扩展性很差,写得也不够好。这样之后须要添加别的过滤功能不是很方便,老是要修改这个类,一点都不灵活,想把对字符串的过滤行为抽象出来,由于这部分是变化的,天然而然想到使用接口。设计模式

使用接口来剥离行为

代码修改成:数组

public String processor(){
    if(null != msg && !("").equals(msg.trim())){
        msg = new HTMLFilter().doFilter(msg);
        msg = new SmileFilter().doFilter(msg);
        msg = new SensitivityFilter().doFilter(msg);
    }
    return msg;
}

这样仍是不够灵活,直接在 ** MsgProcessor ** 类中添加一个数组来保存过滤器,而后在 ** processor** 方法中进行屡次调用:数据结构

修改成:ide

public String processor(){
    if(null != msg && !("").equals(msg.trim())){
        for(Filter f : filters){
            msg = f.doFilter(msg);
        }
    }
    return msg;
}

这样调整后,全部的过滤器都起做用了,添加起来更加灵活一些,而且过滤器的执行顺序也是可控的。学习

当多个过滤器组合在一块儿,就造成了过滤器链,到这里,责任链有点雏形了。this

新的问题

若是原本已经存在一个过滤器链条了,我想把一些新的过滤器链加进去,而且加入的顺序能够随意控制(随意组合任意的过滤器链条),该怎么办呢?设计

定义一个过滤器链类,这这个类中定义添加过滤器的方法,以及运行整个链条上的全部过滤器的方法,而且返回结果。

代码修改成:

MsgProcessor.java :

public class MsgProcessor {
private String msg;

private FilterChain fc;

public FilterChain getFc() {
    return fc;
}
public void setFc(FilterChain fc) {
    this.fc = fc;
}
public String getMsg() {
    return msg;
}
public void setMsg(String msg) {
    this.msg = msg;
}

public String processor(){
    return fc.doFilter(msg);
}
}

FilterChain.java:

public class FilterChain {
List<Filter> filters = new ArrayList<Filter>();

public FilterChain addFilter(Filter filter){
    filters.add(filter);
    return this;
}

public String doFilter(String str){
    if(null != str && !("").equals(str.trim())){
        for(Filter f : filters){
            str = f.doFilter(str);
        }
    }
    return str;
}
}

TestMain.java

public class TestMain {
public static void main(String[] args) {
    String str = "你好:),这句话中有敏感词汇,须要处理。<script>,敏感!";
    MsgProcessor mp = new MsgProcessor();
    mp.setMsg(str);
    FilterChain fc = new FilterChain();
    fc.addFilter(new HTMLFilter())
    .addFilter(new SmileFilter())
    .addFilter(new SensitivityFilter());
    mp.setFc(fc);
    str = mp.processor();
    System.out.println(str);
}
}

写到这里,仍是没有解决咱们的问题,怎样灵活合并过滤器链呢? 很简单,咱们能够将过滤器链这个类,看成一个很大的过滤器来处理,这样就能够了。让** FilterChain **也实现Filter接口,这样就解决了这个问题!完成这一步,就已经有了责任链模式的味道了!

思考实际开发中的问题

在实际开发中,咱们见过的过滤器都能进行双向的处理,也就是说,能处理request和response,并且是先挨着处理request,而后再反向处理response,这又是怎么实现的呢? 过滤器链图

定义一个Request和Response,在实际的web容器中,容器会帮助咱们生成这两个对象,并且在其中封装了不少的东西,在这里,只是模拟,只需简单定义就能够了。

Request.java

public class Request {
private String requestStr;
public String getRequestStr() {
    return requestStr;
}
public void setRequestStr(String requestStr) {
    this.requestStr = requestStr;
}
}

Response.java

public class Response {
private String responseStr;
public String getResponseStr() {
    return responseStr;
}
public void setResponseStr(String responseStr) {
    this.responseStr = responseStr;
}
}

定义好这两个类以后,修改以前的程序:

Filter.java

public interface Filter {
    public abstract void doFilter(Request request, Response response);
}

别的代码跟着这个接口一块儿改就能够了,可是你会发现,仍是不能实现咱们想要的效果,这个时候须要一些编程的手法,咱们继续修改Filter接口:

Filter.java

public interface Filter {
    public abstract void doFilter(Request request, Response response, FilterChain filterChain);
}

为何要这样修改,由于只有这样才能把链条握在每个过滤器手中,有了链条,就能够控制链条了:

FilterChain.java

public class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<Filter>();
private int index = 0;
public FilterChain addFilter(Filter filter){
    this.filters.add(filter);
    return this;
}
@Override
public void doFilter(Request request, Response response,
        FilterChain filterChain) {
    if(index >= filters.size()) return;
    Filter f = filters.get(index);
    index++;
    f.doFilter(request, response, filterChain);
}
}

HTMLFilter.java

public class HTMLFilter implements Filter {
@Override
public void doFilter(Request request, Response response,
        FilterChain filterChain) {
    String str = request.getRequestStr();
    System.out.println(str);
    filterChain.doFilter(request, response, filterChain);
    String resStr = response.getResponseStr();
    System.out.println(resStr);
}
}

如今来看,每一个过滤器都持有过滤器链,在处理完request后,调用下一个过滤器,因为方法是栈结构,这样就会造成一个过滤器栈,拥有栈的数据结构特色。这也是为何Struts在配置多个拦截器的时候,成为拦截器栈的缘由。 因为栈的数据特色,就能达到咱们想要的特色,按照过滤器的次序,依次处理完request,而后再反向依次处理response。这就是责任链模式在实际开发中的使用。

相关文章
相关标签/搜索