上一篇 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
网友评论