组件对外接口设计-易用性
示例
OKHttp网络请求:
FormBody formBody = new FormBody.Builder().add("pay_fee", String.valueOf(product.getProductPrice())).add("product_name", String.valueOf(product.getProductName())).add("access_token", "").build();Request request = new Request.Builder().post(formBody).url(createOrderURL).build();OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(null);
Glide的图片加载:
Glide.with(this).load(sampledPhotoPath).asBitmap().format(DecodeFormat.ALWAYS_ARGB_8888).skipMemoryCache(true).transform(new FilterEffectBitmapTransformation(this,mFilterInfo, sampledPhotoPath)).into(mBinding.appBeautyFilterMarkPhotoIv);
调用上面的代码的感觉“爽”,接口简单,方便的网络请求,方便的图片加载。从上面的代码代码看出接口的定义非常易用。我们该怎么写出如此简单易用的接口?下面我们一起探讨一下。
从上面代码可以看出配置的时候的使用了.的一步步的连接起来,其实这种方式采用了Builder模式,使得接入的时候非常方便,而且代码很清晰。
OKHttp结构图:
OKHttp的接口
- 对外接口
- OkHttpClient, Builder用于全局的请求配置和作为Call的工厂方法
- Request,Builder, RequestBody用于构建请求数据
- Call可执行的网络请求
- 底层接口执行网络请求,比如Dispather请求分发,Interceptor,Chain等类被上层接口封装,不暴露给client。
Glide的结构图:
Glide的接口:
- 对外接口:
- Glide,RequestManager,GenericRequestBuilder封装了底层接口
- 底层接口是实际的图片加载。基本不暴露给client使用,除非涉及到了相关的配置。
其实上面的对外接口的设计用到了一种设计模式Facade模式。此模式封装子系统,向外提供了更高层的接口主要有以下几个好处:
- 提高了对外接口的易用性,降低了接入成本
- 子系统的不想暴露的接口可以隐藏,更好的体现了面向对象的思想。
- 子系统做兼容,或者是代码重构,亦或是流程修改,只要高层接口不改变,不会影响到client。
从上面我们得出了提高对外接口的易用性的常用的设计方式
- Builder模式用于配置
- Facade模式封装子系统来提供对外的高层接口
下面我们就简单介绍一下如何使用这两种设计模式。
设计模式
Builder模式
基础知识,可参考 刘伟的博客。
建造者模式(一)
建造者模式(二)
建造者模式(三)
这个模式在对外接口设计中一般用于配置或者构建复杂对象。
比如OKHttp里的配置:
OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).build();
为了简化这里只是列举了部分信息。
public static final class Builder {int connectTimeout;int readTimeout;public Builder() {connectTimeout = 10_000;readTimeout = 10_000;}Builder(OkHttpClient okHttpClient) {this.connectTimeout = okHttpClient.connectTimeout;this.readTimeout = okHttpClient.readTimeout;}public Builder connectTimeout(long timeout, TimeUnit unit) {connectTimeout = checkDuration("timeout", timeout, unit);return this;}public Builder readTimeout(long timeout, TimeUnit unit) {readTimeout = checkDuration("timeout", timeout, unit);return this;}public OkHttpClient build() {return new OkHttpClient(this);}
}
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {final int connectTimeout;final int readTimeout;public OkHttpClient() {this(new Builder());}OkHttpClient(Builder builder) {this.connectTimeout = builder.connectTimeout;this.readTimeout = builder.readTimeout;}public int connectTimeoutMillis() {return connectTimeout;}public int readTimeoutMillis() {return readTimeout;}}
- Builder构建OkHttpClient的时候,客户端可以配置信息,然后调用build就可以构建成功。
- Builder构建OKHttpClient的时候,readTimeout接口或者connectTimeout接口返回Builder对象,这样的客户端调用的时候只需要用.来连接相关的方法,更加方便。
大家也可以查看GenericRequestBuilder如何构建Request的,或者Android的Intent的类,来了解Builder的使用。
实现的技巧:
- 实现的时候必要参数可以在构造函数中传递,其他的使用接口设置
- Builder的类返回的函数可以返回当前的对象,以此可以使用调用的.的符号记性连接。
Facade设计模式
为子系统的一组接口提供一个一致的界面,Facade模式定义了一些高层接口,这些接口使得子系统更加容易使用。
下面以我以前做的游戏联运的SDK为例。
对外提供接口这里使用了Facade模式,
- MTOnlieGameSDK为主要的对外的高层接口类。
- MTOnlieGameSDK封装了其他子系统,MTAccountManager,MTPayManager
- 同时MTAccountManager,MTPayManager也使用了Facade模式,MTAccountManager封装帐号SDK,MTPayManager封装了与支付APK的通信。
Notice:
- 封装了子系统对外的接口得到简化,提高了对外接口的易用性。
- 使用Facade模式封装更高层的接口,避免了不必要的接口的暴露,同时子系统与客户端代码分离,提高了代码的独立性。比如更改MTAccountManager的实现不会影响到client的代码修改。
此外在层次结构接口中引入Facade模式封装每个层级,可以简化层级之间的依赖。
其他问题
- 接口的暴露,不需要的接口尽量不暴露用户。
- 参数的数量的问题,一方面尽量减少参数,一般参数3个左右为宜,多了可以使用封装成类进行传递。
- 参数依赖抽象类,比如Activity和Context的使用,能使用Context尽量不要使用Activity等等。也就是尽量使用接口而不是具体类。
- 工厂方法或者抽象工厂来创建对象。比如OKHttp的Call.Factory。
注意:
- 设计模式的使用只是为了得到好的代码设计,而过度使用会造成冗余,三思再用。
- 设计模式的使用不要过于依赖所谓的类图或者结构图,往往稍微变化的设计模式更好用。
参考资料
- 设计模式-可复用面向对象软件的基础 只服四人帮的这本书,虽然例子和内容过时了,但设计思想杠杠的。
- LoveLion的博客
`
组件对外接口设计-易用性相关推荐
- 对系统组件化接口设计的一点看法
今天海浪分享一篇对系统组件化接口设计的一点看法.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:of ...
- 其他系统 对外接口设计_外观模式:统一接口 VS.暴露细节
什么是接口--java语言中的接口 Java类中定义的所有public型的方法都可以被简单地视为该类对外提供的接口. 抽象类中public型的抽象方法,可以被看成是整棵继承树的对外接口. 对于Java ...
- 其他系统 对外接口设计_设计模式分类及设计原则
点击蓝字,关注我们 01 概述 设计模式的基础是:多态. 学习设计模式将有助于更加深入地理解面向对象思想,让你知道: 1.如何将代码分散在几个不同的类中? 2.为什么要有"接口"? ...
- 其他系统 对外接口设计_领导:项目有个接口要对外开放,小张你来设计一下?...
前言 最近有个项目需要对外提供一个接口,提供公网域名进行访问,而且接口和交易订单有关,所以安全性很重要:这里整理了一下常用的一些安全措施以及具体如何去实现. 安全措施 个人觉得安全措施大体来看主要在两 ...
- 16. 设计模式之契约原则:如何做好 API 接口设计?
一.契约式设计原则:API 设计的指导书 无论是架构设计还是编码实现,现在都越来越离不开接口设计,接口可以说是新时代的"集装箱",是得到了几乎所有人一致共识的通用标准. GoF 在 ...
- 优秀的API接口设计原则及方法
一旦API发生变化,就可能对相关的调用者带来巨大的代价,用户需要排查所有调用的代码,需要调整所有与之相关的部分,这些工作对他们来说都是额外的.如果辛辛苦苦完成这些以后,还发现了相关的bug,那对用户的 ...
- API接口设计之RESTful软件架构风格
说到API接口设计有的喜欢用Web Service,有的喜欢用WCF,当然也有还在用最原始的ashx,aspx页面的.无论采用什么方式能很好的满足业务需求就ok,但是不同的方式在扩展性.易用性,可维护 ...
- 腾讯技术分享:微服务接口设计原则
来源|腾讯技术工程(ID:Tencent_TEG) 本文结合自身后台开发经验,从高可用.高性能.易维护和低风险(安全)角度出发,尝试总结业界常见微服务接口设计原则,帮助大家设计出优秀的微服务. 1.前 ...
- 接口设计,这36个核心知识点一定要注意
目录 前言 设计好接口的 36 个锦囊 总结 前言 作为后端开发,不管是什么语言,Java.Go 还是 C++,其背后的后端思想都是类似的.我们做后端开发工程师,主要工作就是:如何把一个接口设计好.所 ...
最新文章
- Linux入门(四)
- Android vector标签 PathData 画图超详解
- Exchange Server 2016管理系列课件53.DAG管理之设置滞后数据库副本
- 散列(hash)练习题
- [css] img标签是行内元素,为什么却能设置宽高
- 数据管理,数据治理,数据中心,数据中台,数据湖这下就分清楚了!
- JQuery 绑定事件
- anaconda 安装在c盘_Anaconda安装和使用原来这么简单...
- 冒泡、选择、快速、归并、堆排序算法 python实现
- 家到学校路线图怎么画_从家到学校的详细地图怎么画?
- 《NAT穿越(NAT-T)RFC3947文档》记录
- 华为员工吐槽加班太多,晒出7天上班打卡记录网友:不怕猝死吗?
- linux lsof详解
- Python(贪心算法)问题 D: 删数问题_输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数。
- python 免费空间_用python做大数据
- PowerDesigner根据数据库生成数据字典
- python批量检索文献pubmed_如何使用PubMed高效检索文献
- python生成word 带目录_利用python程序生成word和PDF文档的方法
- 2021-06-11警告: 多个不同应用注册了相同服务,请检查
- 让Windows系统自动登陆,支持XP 2003 win7 win2008 win10