OkHttp之责任链模式设计与使用

作者: Dotry | 来源:发表于2020-01-06 16:48 被阅读0次

    前言

    最近查看OkHttp 请求框架,发现里面过滤器用的非常灵活,而其整个设计模式就是采用责任链模式来设计的,这篇博客主要用来讨论一下责任链相关设计与使用。

    责任链模式

    一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程。同样网络请求中也存在一些列的流程,这也是OkHttp采用该模式的主要原因。下面以一个采购场景来作说明:

    假设公司要采购一批物料,采购流程一般是如下图: 采购.jpg 采购员->主管->经理->总经理这是一个完整的采购流程。

    代码实现:

    Employee

    public class Employee {
        private String name;
        private String msg;
        private int price;
        public int getPrice() {
            return price;
        }
        public void setPrice(int price) {
            this.price = price;
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    

    ApplyFilter

    public interface ApplyFilter {
        boolean doFilter(Employee employee,ApplyFilterChain chain);
    }
    

    ApplyFilterChain

     public class ApplyFilterChain implements ApplyFilter {
        List<ApplyFilter> filters = new ArrayList<>();
        int index = 0;
        public ApplyFilterChain add(ApplyFilter applyFilter){
            filters.add(applyFilter);
            return this;
        }
    
        @Override
        public boolean doFilter(Employee employee,ApplyFilterChain chain) {
            if (index>=filters.size()) return false;
            ApplyFilter filter = filters.get(index);
            index ++;
            filter.doFilter(employee,chain);
            return true;
        }
    }
    

    SupervisorApplyFilter

    
    /**
     * 主管审批
     */
    public class SupervisorApplyFilter implements  ApplyFilter{
    
        @Override
        public boolean doFilter(Employee employee,ApplyFilterChain chain) {
            if (employee.getPrice()<=100){
                System.out.println("资金小于100主管审批通过,流程结束");
                employee.setMsg(employee.getMsg()+"资金小于100主管审批通过,流程结束");
                return false;
            }else {
                System.out.println("资金大于100主管请经理审批");
                employee.setMsg(employee.getMsg()+"资金大于100主管请经理审批->");
                chain.doFilter(employee,chain);
                return true;
            }
        }
    }
    
    

    ManagerApplyFilter

    
    /**
     * 经理审批
     */
    
    public class ManagerApplyFilter implements  ApplyFilter{
    
        @Override
        public boolean doFilter(Employee employee ,ApplyFilterChain chain) {
            if (employee.getPrice()<=500){
                System.out.println("资金小于500经理审批通过,流程结束");
                employee.setMsg(employee.getMsg()+"资金小于500经理审批通过,流程结束");
                return false;
            }else {
                System.out.println("资金大于500经理请总经理审批");
                employee.setMsg(employee.getMsg()+"资金大于500经理请总经理审批->");
                chain.doFilter(employee,chain);
                return true;
            }
        }
    }
    

    GeneralManagerApplyFilter

    /**
     * 总经理审批
     */
    
    public class GeneralManagerApplyFilter implements  ApplyFilter{
        @Override
        public boolean doFilter(Employee employee ,ApplyFilterChain chain) {
            if (employee.getPrice()<=5000){
                System.out.println("资金小于5000总经理审批通过,流程结束");
                employee.setMsg(employee.getMsg()+"资金小于5000总经理审批通过,流程结束");
                return false;
            }else {
                System.out.println("资金大于5000, 总经理需要开会讨论,流程结束");
                employee.setMsg(employee.getMsg()+"资金大于5000, 总经理需要开会讨论,流程结束");
                return true;
            }
        }
    }
    
    

    以上为一个完整的chain如果中间某个环节可以结束该流程,则后续的流程不用处理,这也是通过doFilter 的返回值来确定下一个流程是否继续,这个是一个递归的思想,也是比较难以理解的地方。
    Main

    public class Main {
    
        public static void main(String[] args) {
            Employee employee = new Employee();
            employee.setMsg("物料采购申请->");
            employee.setPrice(10);
            ApplyFilterChain applyFilterChain = new ApplyFilterChain();
            applyFilterChain.add(new SupervisorApplyFilter()).add(new ManagerApplyFilter()).add(new GeneralManagerApplyFilter());
            applyFilterChain.doFilter(employee,applyFilterChain);
            System.out.println(employee.getMsg());
        }
    }
    

    得出的结果如下:

    资金小于100主管审批通过,流程结束
    物料采购申请->资金小于100主管审批通过,流程结束
    

    以上是关于责任链模式的使用。

    3 OkHttp

    关于OkHttp 中过滤器的问题可以查看到RealCall类中:

     Response getResponseWithInterceptorChain() throws IOException {
        // Build a full stack of interceptors.
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.addAll(client.interceptors());
        interceptors.add(retryAndFollowUpInterceptor);
        interceptors.add(new BridgeInterceptor(client.cookieJar()));
        interceptors.add(new CacheInterceptor(client.internalCache()));
        interceptors.add(new ConnectInterceptor(client));
        if (!forWebSocket) {
          interceptors.addAll(client.networkInterceptors());
        }
        interceptors.add(new CallServerInterceptor(forWebSocket));
    
        Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
            originalRequest, this, eventListener, client.connectTimeoutMillis(),
            client.readTimeoutMillis(), client.writeTimeoutMillis());
    
        return chain.proceed(originalRequest);
      }
    

    其不断添加过滤器,但最后的过滤器为CallServerInterceptor由此可以得出结论,最终请求网络等想过操作,就是在该类中进行,查看代码果真如此。
    以上是关于在OkHttp中发现的责任链模式的使用,其详细介绍可以参考设计模式 | 责任链模式及典型应用这篇文章写得比较清楚。

    相关文章

      网友评论

        本文标题:OkHttp之责任链模式设计与使用

        本文链接:https://www.haomeiwen.com/subject/kuqkactx.html