设计模式知识梳理(5) - 结构型 - 外观模式

2018-11-26  本文已影响39人  泽毛

一、基本概念

1.1 定义

要求一个子系统的外部与其内部的通信必须通过一个 统一的对象 进行,外观模式提供一个高层次的接口,使得子系统更易于使用。即使具体的子系统发生了变化,用户也不会感知到。

1.2 例子

外观模式

外观模式接口比较简单,就是通过一个统一的接口对外提供服务,使得外部程序只 通过一个类就可以实现系统内部的多种功能,而这些实现功能的内部子系统之间可能也有交互,通过外观类来屏蔽这些复杂的交互,降低用户的使用成本。

由于这种模式比较简单,不容易与其它的模式混淆,这里就不举简单的例子了。

1.3 应用场景

1.4 优缺点

优点

缺点

二、Android 源码

当我们启动一个新页面的时候,只需要调用startActivity方法,如 Framework 源码解析知识梳理(1) - 应用进程与 AMS 的通信实现 一文中分析的,在其背后做了很多调用者不可见的工作:

这其实就是外观模式的运用,使用者不必关心里面的具体实现,它只需要将启动的意图信息放在Intent当中,之后就交给系统自己去处理了。如果在之后的版本中,需要修改行为,也不会影响到调用者。

三、项目运用

之前在项目当中直接使用OKHttp的时候,由于没有封装,缓存也是由业务自己去处理,非常混乱,如果要实现一个带缓存的请求很麻烦。从业务层面来说,使用第三方框架时,有几个痛点无法满足,但是又是很多业务需要用到的:

之后就对网络请求做了统一的封装,这其实就是外观模式的典型运用。

网络框架封装
在发起请求的时候,只需要构造一个NetRequest对象,在该对象中可以进行各种参数的配置。
public class NetRequest {

    private long expireTime;
    private String url;
    private Map<String, String> queryMaps = new HashMap<>();
    private Map<String, String> headerMaps = new HashMap<>();
    private ResponseProcessor responseProcessor;
    private @CacheType
    int cacheType;
    private boolean dealOnUiThread;
    private @RequestType
    int requestType;
    private @ContentType
    String contentType;
    private @Encoding
    String encoding = Encoding.UTF_8;
    private String paramJson;
    private String paramForm;
    private Map<String, String> params = new HashMap<>();
    private boolean noCache;
    private List<INetCallback> netCallbacks;
    private String cacheKey;
    private IProgressCallback progressCallback;
    private boolean filterEqualBody;

    //...
}

发起网络请求的时候,只需要调用NetExecutor#doAsync(NetRequest netRequest)方法传入配置好的请求对象就可以了,在内部会去解析NetRequest当中的参数,完成最终的网络请求,并将结果封装成NetResponse返回,加入我们后面需要新增功能,那么只需要修改系统内部的实现就可以了。

public class NetHttpImpl extends INetHttp {


    public NetHttpImpl(NetExecutor netExecutor) {
        super(netExecutor);
    }

    @Override
    public <T> NetResponse<T> doRealHttpRequest(NetRequest netRequest, NetResponse<T> cacheResponse) {
        NetResponse<T> netResponse;
        try {
            //添加拦截器监听。
            addInterceptorListener(netRequest);
            //创建 OkHttp 的 Request。
            final Request trueHttpRequest = createHttpRequest(netRequest);
            Call call = netExecutor.getOkHttpClient().newCall(trueHttpRequest);
            okhttp3.Response httpResponse = call.execute();
            //正常情况下,将 OkHttp 的 Response 转换为调用者看到的 NetResponse。
            netResponse = dealHttpResponse(netRequest, httpResponse);
        } catch (Exception e) {
            //异常情况下,将 OkHttp 的 Response 转换为调用者看到的 NetResponse。
            netResponse = dealHttpException(e);
        } finally {
            //取消拦截器的监听。
            removeInterceptorListener(netRequest);
        }
        return netResponse;
    }

    /**
     * 通过请求配置创建 OkHttp 的 request。
     * @param netRequest 请求配置。
     * @return OkHttp 的请求。
     */
    private okhttp3.Request createHttpRequest(NetRequest netRequest) {
        okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
        //1.添加 url。
        addHttpRequestUrl(netRequest, requestBuilder);
        //2.添加请求header 参数。
        addHttpRequestHeader(netRequest, requestBuilder);
        //3.创建请求的 body。
        addHttpRequestBody(netRequest, requestBuilder);
        //4.创建请求。
        return requestBuilder.build();
    }

}

四、参考文献

上一篇下一篇

猜你喜欢

热点阅读