设计模式-责任链模式

简介: 理解 责任链的执行序列是一环连着一环,后一环的执行依赖前一环的执行,层层递进. 流程图 组成部分 链条:负责承前启后; 链条上的环:执行业务逻辑,决定是否继续执行下一个环(有的情况由链条决定); 执行流: 前期:由外层到里层; 后期:由里层到外层 特点 链条上相邻的环之间会影响,.

理解





责任链的执行序列是一环连着一环,后一环的执行依赖前一环的执行,层层递进.



流程图









组成部分

  1. 链条:负责承前启后;
  2. 链条上的环:执行业务逻辑,决定是否继续执行下一个环(有的情况由链条决定);
  3. 执行流:
  4. 前期:由外层到里层;
  5. 后期:由里层到外层

特点

  1. 链条上相邻的环之间会影响,影响入参和出参;
  2. 每个环负责相对独立的任务,比如有的负责字符编码设置,有的负责流的编码和解码(比如gzip),有的负责记录日志等

实例

一个简单的 demo





项目代码

链条类

public class DaoFilterChain {
    private List<IFilter> filterList = new ArrayList<>();
    private int index = 0;
    private boolean hasAddDefaultFilter = false;

    public DaoFilterChain addFilter(IFilter filter) {
        if (hasAddDefaultFilter) {
            throw new RuntimeException("自定义过滤器必须在默认过滤器之前添加");
        }
        this.filterList.add(filter);
        return this;
    }

    /***
     * 专门添加最基础的DaoFilter
     * @param filter
     * @return
     */
    public DaoFilterChain addDefaultFilter(IFilter filter) {
        this.filterList.add(filter);
        hasAddDefaultFilter = true;
        return this;
    }

    public void reset() {
        this.index = 0;
    }

    private IFilter next() {
        if (index == filterList.size()) {
            return null;
        }
        IFilter filter = filterList.get(index);
        index++;
        return filter;

    }


    public void doFilter(DaoRequest request, DaoResponse response) {
        IFilter filter = next();
        if (null == filter) {
            System.out.println("结束 index :" + index);
            return;
        }
        filter.doFilter(request, response, this);
    }


}

过滤器接口

public interface IFilter {
    /***
     * 最后一个过滤器一定是DefaultDaoFilter
     * @param request
     * @param response
     * @param filterChain
     */
    void doFilter(DaoRequest request, DaoResponse response, DaoFilterChain filterChain);
}

javax.servlet.Filter


过滤器核心方法 :

public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain)
        throws IOException, ServletException;


链条:org.apache.catalina.core.ApplicationFilterChain
源码见:http://www.docjar.com/html/api/org/apache/catalina/core/ApplicationFilterChain.java.html



doFilter 核心代码 (去掉了其他代码):

ApplicationFilterConfig filterConfig = filters[pos++];
     Filter filter = null;
     filter = filterConfig.getFilter();
     filter.doFilter(request, response, this);


过滤器实例 :支持跨域





其他过滤器实例



租户拦截器


image.png


接口:

public interface IRequestFilter {
    void doFilter(HttpFormContentRequestWrapper request, HttpServletResponse response, RequestFilterChain filterChain) throws IOException, ServletException;
}


image.png

链条类 RequestFilterChain


public class RequestFilterChain {
    private List<IRequestFilter> filterList = new ArrayList<>();
    private final static Logger logger = LoggerFactory.getLogger(RequestFilterChain.class);
    private ThreadLocal<Integer> indexLocal = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return 0;
        }
    };
    private ThreadLocal<Boolean> hasAddDefaultFilter = new ThreadLocal<Boolean>() {
        @Override
        protected Boolean initialValue() {
            return Boolean.FALSE;
        }
    };

    public RequestFilterChain addFilter(IRequestFilter filter) {
        if (hasAddDefaultFilter.get()) {
            throw new RuntimeException("自定义过滤器必须在默认过滤器之前添加");
        }
        this.filterList.add(filter);
        return this;
    }

    public RequestFilterChain removeFilter(IRequestFilter filter) {
        this.filterList.remove(filter);
        return this;
    }

    public RequestFilterChain addDefaultFilter(IRequestFilter filter) {
        this.filterList.add(filter);
        hasAddDefaultFilter.set(true);
//        DefaultFormRequestWrapperFilter defaultDaoFilter = (DefaultFormRequestWrapperFilter) filter;
        return this;
    }

    public void reset() {
        indexLocal.set(0);
    }

    private IRequestFilter next() {
        if (indexLocal.get() == filterList.size()) {
            return null;
        }
        IRequestFilter filter = filterList.get(indexLocal.get());
//        index++;
        indexLocal.set(indexLocal.get() + 1);
        return filter;

    }

    public void doFilter(HttpFormContentRequestWrapper request, HttpServletResponse response) throws IOException, ServletException {
        IRequestFilter filter = next();
        if (null == filter) {
            return;
        }
        try {
            filter.doFilter(request, response, this);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

}

MultipleTenantsFilter 做了什么


image.png


适用场景

  1. 同时有请求和应答的场景,例如HTTP请求,数据库查询;
  2. 映射层转化
  3. 需要决定是否中断流程的执行;
  4. 业务的执行分为多个中间环节,中间环节的个数可以定制;

和aop的区别


aop体现的是代理模式,实际是动态代理或 cglib

感想

  1. 责任链模式,依然符合开闭原则,比如由于业务的发展,需要添加新的逻辑,那么就可以增加一个过滤器,而不用修改原来的逻辑处理;
  2. 对于逻辑比较复杂,且容易变动的逻辑,可以充分使用责任链模式,把相对聚合的逻辑抽取出来,作为一个个环,后面增加新的逻辑只需要增加新的环即可,也可以根据实际需求修改链条上环的顺序。


相关文章
|
7月前
|
设计模式 Java
【设计模式系列笔记】责任链模式
责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它。每个处理者都有一个对下一个处理者的引用。责任链模式常用于处理请求的场景,例如在一个请求需要经过多个步骤或者多个对象来处理的情况下。
83 0
|
7月前
|
设计模式 Java
【设计模式】责任链模式
【设计模式】责任链模式
|
7月前
|
设计模式
【设计模式】责任链模式
【1月更文挑战第27天】【设计模式】责任链模式
|
27天前
|
设计模式 JavaScript Scala
Kotlin - 改良设计模式 - 责任链模式
Kotlin - 改良设计模式 - 责任链模式
41 3
|
2月前
|
设计模式 JavaScript Scala
Kotlin - 改良设计模式 - 责任链模式
Kotlin - 改良设计模式 - 责任链模式
56 9
|
18天前
|
设计模式 JavaScript Scala
Kotlin教程笔记(55) - 改良设计模式 - 责任链模式
Kotlin教程笔记(55) - 改良设计模式 - 责任链模式
25 0
|
1月前
|
设计模式 JavaScript Scala
Kotlin教程笔记(55) - 改良设计模式 - 责任链模式
Kotlin教程笔记(55) - 改良设计模式 - 责任链模式
37 0
|
2月前
|
设计模式 JavaScript Scala
Kotlin - 改良设计模式 - 责任链模式
本教程详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。对于希望快速上手Kotlin的读者,推荐查阅“简洁”系列教程。本文通过学生会经费申请的例子,介绍了责任链模式及其在Kotlin中的实现,并使用偏函数进行了改进,使代码更加简洁和灵活。
16 0
|
2月前
|
设计模式 JavaScript Scala
Kotlin - 改良设计模式 - 责任链模式
Kotlin - 改良设计模式 - 责任链模式
39 0
|
2月前
|
设计模式 JavaScript Scala
Kotlin学习笔记 - 改良设计模式 - 责任链模式
Kotlin学习笔记 - 改良设计模式 - 责任链模式
45 0