美文网首页
设计模式知识梳理(5) - 结构型 - 外观模式

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

作者: 泽毛 | 来源:发表于2018-11-26 22:07 被阅读39次

一、基本概念

1.1 定义

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

1.2 例子

外观模式

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

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

1.3 应用场景

  • 为一个复杂子系统提供一个简单接口。
  • 当你需要一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。

1.4 优缺点

优点

  • 对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合。
  • 外观类对子系统的接口封装,使得系统更易于使用。

缺点

  • 外观类接口膨胀,由于子系统的接口都由外观类统一对外暴露,使得外观类的API接口较多,在一定程度上增加了用户的使用成本。
  • 外观类没有遵循开闭原则,当业务发生变更时,可能需要直接修改外观类。

二、Android 源码

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

  • 当我们调用startActivity,其实是通过其基类ContextWrapper中的mBase对象来实现的,它的类型为ContextImpl
  • ContextImpl又调用了InstrumentationexecStartActivity方法,它再通过应用侧的ActivityManagerProxyActivityManagerService完成Binder通信,向管理者发送信息。
  • 管理者再通过ApplicationThreadProxy向应用侧发送回执消息。

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

三、项目运用

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

  • 缓存处理
  • 第一次进入无网,需要配置默认数据
  • 返回数据的JSON解析,默认数据的读取,都避免放在耗时的主线程中
  • 回调结果的线程可配置
  • 请求日志的统一处理
  • 直接使用第三方框架侵入性太大,对于业务来说,只关心请求和返回,不应当与具体的网络框架耦合

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

网络框架封装
在发起请求的时候,只需要构造一个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();
    }

}

四、参考文献

  • <<Android 源码设计模式 - 解析与实战>>

相关文章

网友评论

      本文标题:设计模式知识梳理(5) - 结构型 - 外观模式

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