美文网首页
OkHttp设计模式剖析(三)策略模式

OkHttp设计模式剖析(三)策略模式

作者: YongtaoHuang | 来源:发表于2019-07-13 21:56 被阅读0次

    上一篇 OkHttp设计模式剖析(二)责任链模式

    下一篇 OkHttp设计模式剖析(四)享元模式

    OKHTTP:

    由大名鼎鼎的Square公司开发的网络通信库。

    设计模式:

    软件开发中问题的解决套路。

    策略模式简介

    定义:策略模式定义了一系列封装好的可以相互替换的算法

    策略模式让算法独立于使用它的客户而独立变化。将可以互相替换的算法封装成一个一个的类,任意地替换。从而降低if...else 所带来的复杂和难以维护。

    若源代码中有Strategy这个词,大概率使用了策略模式。

    CacheStrategy类中的策略模式

    事实上,CacheStrategy类中的策略模式并不是典型的策略模式(没用定义不同的策略类,依旧使用ifelse做选择),但是其选择合适策略的思想是一致的。
    缓存拦截器CacheInterceptor部分源码:解析来自缓存的请求并讲响应写入缓存。

    public final class CacheInterceptor implements Interceptor {
      final InternalCache cache;
    
      public CacheInterceptor(InternalCache cache) {
        this.cache = cache;
      }
    
      @Override 
      public Response intercept(Chain chain) throws IOException {
        Response cacheCandidate = cache != null
            ? cache.get(chain.request())
            : null;
    
        long now = System.currentTimeMillis();
        // 选择策略
        CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get(); 
        ......
      }
    }
    

    其中,通过CacheStrategy.Factory().get()选择合适的缓存拦截器策略,此处还使用了工厂模式。

    CacheStrategy类用来通过networkRequest和cacheResponse的状态获取合适的缓存拦截器策略。(缓存拦截器本人暂不了解,后期再补充)

    public final class CacheStrategy {
      // 在网络上发送的请求,若此请求不使用网络,则为空
      public final Request networkRequest;
      // 对缓存响应的返回或者验证,若此请求不使用缓存,则为空
      public final Response cacheResponse;
      private CacheStrategy(Request networkRequest, Response cacheResponse) {
        this.networkRequest = networkRequest;
        this.cacheResponse = cacheResponse;
      }
      public static class Factory {
    
        public Factory(long nowMillis, Request request, Response cacheResponse) {......}
    
        // 通过缓存响应返回一个符合request的策略
        public CacheStrategy get() {
          CacheStrategy candidate = getCandidate();
          return candidate;
        }
    
        // 返回策略
        private CacheStrategy getCandidate() {
          // 无缓存响应
          if (cacheResponse == null) {
            return new CacheStrategy(request, null);
          }
    
          // 若丢失请求握手,则放弃缓存响应
          if (request.isHttps() && cacheResponse.handshake() == null) {
            return new CacheStrategy(request, null);
          }
          // 若不可以缓存
          if (!isCacheable(cacheResponse, request)) {
            return new CacheStrategy(request, null);
          }
          // 判断请求的缓存控制字段(此处暂时不了解)
          CacheControl requestCaching = request.cacheControl();
          if (requestCaching.noCache() || hasConditions(request)) {
            return new CacheStrategy(request, null);
          }
          ......
          // 缓存在有效期内
          if (!responseCaching.noCache() && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) {
            Response.Builder builder = cacheResponse.newBuilder();
            if (ageMillis + minFreshMillis >= freshMillis) {
              builder.addHeader("Warning", "110 HttpURLConnection \"Response is stale\"");
            }
            long oneDayMillis = 24 * 60 * 60 * 1000L;
            if (ageMillis > oneDayMillis && isFreshnessLifetimeHeuristic()) {
              builder.addHeader("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
            }
            return new CacheStrategy(null, builder.build()); // 建造出缓存
          }
    
          // 缓存超期
          String conditionName;
          String conditionValue;
          if (etag != null) {
            conditionName = "If-None-Match";
            conditionValue = etag;
          } else if (lastModified != null) {
            conditionName = "If-Modified-Since";
            conditionValue = lastModifiedString;
          } else if (servedDate != null) {
            conditionName = "If-Modified-Since";
            conditionValue = servedDateString;
          } else {
            return new CacheStrategy(request, null); // 此处为发送一个正常请求
          }
          // 添加请求头
          Headers.Builder conditionalRequestHeaders = request.headers().newBuilder();
          Internal.instance.addLenient(conditionalRequestHeaders, conditionName, conditionValue);
    
          Request conditionalRequest = request.newBuilder()
              .headers(conditionalRequestHeaders.build())
              .build();
          return new CacheStrategy(conditionalRequest, cacheResponse);
        }
      }
    }
    

    上述代码大致可以归纳成4个选择:
    1、networkRequest = null && cacheResponse != null
    2、networkRequest = null && cacheResponse != null
    3、networkRequest != null && cacheResponse = null
    4、networkRequest != null && cacheResponse = null
    由此根据展开分别选取不同策略。

    基于策略模式构建的其他代码

    1、Android源码中Animation对象不同的插值器
    2、Hibernate的对于SQL不同方言的策略

    排序算法的选择

    举快速排序和选择排序为例,伪代码如下:

    public interface SortAlg{}
    
    public class QuickSort implements SortAlg{
        // 快速排序 时间复杂度O(nlogn) 空间复杂度O(logn)
    }
    
    public class SelectiveSort implements SortAlg{
        // 选择排序 时间复杂度O(n2) 空间复杂度O(1)
    }
    
    public class ArraySort{
        
        public static void main(String[] args){
            ArraySort as = new ArraySort();
            if( 时间重要性 >= 空间重要性 ){
                as.setSortAlg(new QuickSort()); //选择快速排序    
            }else{
                as.setSortAlg(new SelectiveSort()); //选择选择排序    
            }       
        }
        
        SortAlg sortAlg;
        public void setSortAlg(SortAlg sortAlg){
            this.sortAlg = sortAlg;
        }
        
    }
    

    参考文献

    1、设计模式|菜鸟教程:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
    2、《Android源码设计模式解析与实战》何红辉,关爱民著
    3、隔壁老李头:https://www.jianshu.com/p/82f74db14a18

    上一篇 OkHttp设计模式剖析(二)责任链模式

    下一篇 OkHttp设计模式剖析(四)享元模式

    All is well.

    相关文章

      网友评论

          本文标题:OkHttp设计模式剖析(三)策略模式

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