大数据&云计算|为什么基于接口而非实现编程?有必要为每个类都定义接口吗?
本文插图
我们知道基于接口而非实现编程 。 这个原则非常重要 , 是一种非常有效的提高代码质量的手段 , 在平时的开发中特别经常被用到 。
今天结合一个有关图片存储的实战案例来讲解 。 除此之外 , 这条原则还很容易被过度应用 , 比如为每一个实现类都定义对应的接口 。 针对这类问题 , 在今天的讲解中 , 我也会告诉你如何来做权衡 , 怎样恰到好处地应用这条原则 。
如何解读原则中的“接口”二字?
本文插图
“基于接口而非实现编程”这条原则的英文描述是:“Program to an interface, not an implementation” 。 我们理解这条原则的时候 , 千万不要一开始就与具体的编程语言挂钩 , 局限在编程语言的“接口”语法中(比如 Java 中的 interface 接口语法) 。 这条原则最早出现于 1994 年 GoF 的《设计模式》这本书 , 它先于很多编程语言而诞生(比如 Java语言) , 是一条比较抽象、泛化的设计思想 。
实际上 , 理解这条原则的关键 , 就是理解其中的“接口”两个字 。 还记得我们上一节课讲的“接口”的定义吗?从本质上来看 , “接口”就是一组“协议”或者“约定” , 是功能提供者提供给使用者的一个“功能列表” 。 “接口”在不同的应用场景下会有不同的解读 , 比如服务端与客户端之间的“接口” , 类库提供的“接口” , 甚至是一组通信的协议都可以叫作“接口” 。 刚刚对“接口”的理解 , 都比较偏上层、偏抽象 , 与实际的写代码离得有点远 。 如果落实到具体的编码 , “基于接口而非实现编程”这条原则中的“接口” , 可以理解为编程语言中的接口或者抽象类 。
前面我们提到 , 这条原则能非常有效地提高代码质量 , 之所以这么说 , 那是因为 , 应用这条原则 , 可以将接口和实现相分离 , 封装不稳定的实现 , 暴露稳定的接口 。 上游系统面向接口而非实现编程 , 不依赖不稳定的实现细节 , 这样当实现发生变化的时候 , 上游系统的代码基本上不需要做改动 , 以此来降低耦合性 , 提高扩展性 。 实际上 , “基于接口而非实现编程”这条原则的另一个表述方式 , 是“基于抽象而非实现编程” 。 后者的表述方式其实更能体现这条原则的设计初衷 。 在软件开发中 , 最大的挑战之一就是需求的不断变化 , 这也是考验代码设计好坏的一个标准 。 越抽象、越顶层、越脱离具体某一实现的设计 , 越能提高代码的灵活性 , 越能应对未来的需求变化 。 好的代码设计 , 不仅能应对当下的需求 , 而且在将来需求发生变化的时候 , 仍然能够在不破坏原有代码设计的情况下灵活应对 。 而抽象就是提高代码扩展性、灵活性、可维护性最有效的手段之一 。
如何将这条原则应用到实战中?
本文插图
对于这条原则 , 我们结合一个具体的实战案例来进一步讲解一下 。 假设我们的系统中有很多涉及图片处理和存储的业务逻辑 。 图片经过处理之后被上传到阿里云上 。 为了代码复用 , 我们封装了图片存储相关的代码逻辑 , 提供了一个统一的AliyunImageStore 类 , 供整个系统来使用 。 具体的代码实现如下所示: //... 省略属性、构造函数等...public void createBucketIfNotExisting(String bucketName) {// ... 创建 bucket 代码逻辑...// ... 失败会抛出异常..}public String generateAccessToken() {// ... 根据 accesskey/secrectkey 等生成 access token}public String uploadToAliyun(Image image, String bucketName, String accessTok//... 上传图片到阿里云...//... 返回图片存储在阿里云上的地址 (url)...}public Image downloadFromAliyun(String url, String accessToken) {//... 从阿里云下载图片...}}// AliyunImageStore 类的使用举例public class ImageProcessingJob {private static final String BUCKET_NAME = "ai_images_bucket"//... 省略其他无关代码...public void process() {Image image = ... // 处理图片 , 并封装为 Image 对象AliyunImageStore imageStore = new AliyunImageStore(/* 省略参数 */)imageStore.createBucketIfNotExisting(BUCKET_NAME)String accessToken = imageStore.generateAccessToken()imagestore.uploadToAliyun(image, BUCKET_NAME, accessToken)}}
推荐阅读
- 智能穿戴|漫步者DreamPods体验:外观精致佩戴舒适降噪是最大惊喜
- 数据|智领云荣登“中国大数据企业50强” | 2020大数据产业生态大会盛大召开
- 大数据|华云数据荣获中国大数据50强、2020数字赋能先锋企业30强,入选大数据产业发展白皮书及百佳案例
- 驱动中国|即信Fintech智研中心:银行践行社交化运营的要诀--渠道通 交互通 数据通
- 行业互联网|华云数据荣获中国大数据50强、2020数字赋能先锋企业30强,入选大数据产业发展白皮书及百佳案例
- 技术编程|数据结构001之简介
- 行业互联网|爱数亮相第八届医药健康论坛,以数据赋能药企数字化
- 技术编程|边缘云计算到底是什么?
- 行业互联网|智领云荣登“中国大数据企业50强”| 大数据产业生态大会
- 互联网|图匠数据CTO梁柱锦:利用AI与大数据提升线下零售管理能力 | 公开课预告
