行为型之责任链模式

序言

  责任链模式里有很多对象会有共同的行为方法,其中每一个对象对其下家的引用而连接起来会形成形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

  责任链有如下几种角色:

  • 抽象处理者角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。
  • 具体处理者角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

1. 责任链模式

 
  责任链模式的结构如下图:

![](http://images2017.cnblogs.com/blog/946528/201708/946528-20170819233916053-234157162.png)
``` /** * 抽象处理者角色 */ public abstract class Handler { protected Handler handler; public abstract void handle();
public void setHandler(Handler handler) {
    this.handler = handler;
}

}

/**

  • 具体处理者
    */
    public class ConcreteHandler1 extends Handler {

    @Override
    public void handle() {
    if(handler != null){
    System.out.println("handler1 处理请求中 ...");
    handler.handle();
    }
    }
    }

/**

  • 具体处理者
    */
    public class ConcreteHandler2 extends Handler {
    @Override
    public void handle() {
    System.out.println("handler2 处理请求中 ...");
    }
    }

/**

  • 测试责任链模式
    */
    public class ChainTest {

    @Test
    public void testChain(){
    ConcreteHandler1 handler1 = new ConcreteHandler1();
    ConcreteHandler2 handler2 = new ConcreteHandler2();
    handler1.setHandler(handler2);
    handler1.handle();
    }
    }


###2. 应用场景-过滤器filter

1. 过滤器接口

/**

  1. 过滤器接口
    */
    public interface Filter {
    //request 和response在真正的servlet中是对象,此处简化处理为string
    public void doFilter(String request,String response,FilterChain filterChain);
    }
2. 字符集过滤器

/**

  • 字符编码过滤器
    */
    public class EncodeFilter implements Filter {

    public void doFilter(String request, String response, FilterChain filterChain) {
    System.out.println("对request做utf-8编码");
    filterChain.doFilter(request, response);
    System.out.println("对response做utf-8编码");
    }
    }

3. xss过滤器

/**

  • 防xss攻击过滤器
    */
    public class XssFilter implements Filter {

    public void doFilter(String request, String response, FilterChain filterChain) {
    System.out.println("过滤request的xss内容");
    filterChain.doFilter(request, response);
    System.out.println("过滤response的xss内容");
    }

}

4. servlet接口,仅实现service接口

/**

  • Servelt接口,只模拟了Servlet方法
    */
    public interface Servlet {
    public void service(String request,String response);
    }
5. servlet实现

public class MainServlet implements Servlet {
public void service(String request, String response) {
System.out.println(request);
response="返回response结果";
System.out.println(response);
}
}

6. 过滤器责任链实现

/**

  • 内部处理的filter链,链中保存真正filter的执行顺序
    */
    public class FilterChain {
    private int cursor;
    public List filters = new ArrayList();
    public Servlet servlet;

    public void setServlet(Servlet servlet) {
    this.servlet = servlet;
    }

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

    public void doFilter(String request, String response) {
    if (cursor < filters.size()) {
    filters.get(cursor++).doFilter(request, response, this);
    } else {
    servlet.service(request, response);
    }
    }
    }

7. 测试责任链

/**

  • 测试过滤器
    */
    public class FilterTest {

    @Test
    public void testFileter(){

     //定义filter
     Filter encodeFilter=new EncodeFilter();
     Filter xssFilter=new XssFilter();
     FilterChain chain=new FilterChain();
    
     chain.addFilter(encodeFilter);
     chain.addFilter(xssFilter);
    
     //定义servlet
     Servlet servlet=new MainServlet();
     chain.setServlet(servlet);
     chain.doFilter("发送请求", "");
    

    }

}

>小结:
  1. <span style="color:red">责任链的实现并不是链式结构,而是以一个FilterChain保存了所有责任链的引用,通过FilterChain的doFilter方法依次调用filter进行执行</span>
  2. <span style="color:red">filter中同时也保存了FilterChain的引用,形成了一个双向引用。采用了类似递归、回调的形式确保有入过滤器和出过滤器</span>
  3. <span style="color:red">FilterChain作为web容器的功能,由系统默认提供,我们无需关注其实现原理(注:代码中仅为可能实现的方式)。他依次将web.xml中的filter按照文件排放顺序进行调用执行。</span>

### 后记
>- 撰写本文考了不少博文,在此一并谢过。
[责任链设计模式(过滤器、拦截器)](http://www.flyne.org/article/693)
[责任链模式chain](http://www.cnblogs.com/jyyzzjl/p/5187340.html)
[《JAVA与模式》之责任链模式](http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html)
>- 转载时,请注明出处,这是人格的一种体现。
[https://www.zybuluo.com/BertLee/note/856150](https://www.zybuluo.com/BertLee/note/856150)
>- 能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。
posted @ 2017-08-19 23:40  吃不了兜着走  阅读(182)  评论(0编辑  收藏  举报