设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
123425 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

09 | 理论六:为什么基于接口而非实现编程?有必要为每个类都定义接口吗?

越是不稳定的系统,越需要在代码的扩展性、维护性上下功夫
某个功能只有一种实现方式,未来也不可能被其他实现方式替换,不需要定义接口
为实现类定义抽象的接口
封装具体的实现细节
函数的命名不能暴露任何实现细节
暴露稳定的接口
封装不稳定的实现
将接口和实现相分离
在不同的应用场景下会有不同的解读
功能提供者提供给使用者的一个“功能列表”
一组“协议”或者“约定”
更好的实现思路
问题
原则的指导作用
在定义接口时的注意事项
“基于接口而非实现编程”的设计初衷
根据业务场景和需求
重构代码
“基于接口而非实现编程”的含义
“接口”定义
提高代码的扩展性
降低代码间的耦合性
暴露稳定的接口
封装不稳定的实现
将接口和实现相分离
Program to an interface, not an implementation
课堂讨论
重点回顾
是否需要为每个类定义接口
如何将这条原则应用到实战中
如何解读原则中的“接口”二字
原则的设计初衷
原则
基于接口而非实现编程

该思维导图由 AI 生成,仅供参考

在上一节课中,我们讲了接口和抽象类,以及各种编程语言是如何支持、实现这两个语法概念的。今天,我们继续讲一个跟“接口”相关的知识点:基于接口而非实现编程。这个原则非常重要,是一种非常有效的提高代码质量的手段,在平时的开发中特别经常被用到。
为了让你理解透彻,并真正掌握这条原则如何应用,今天,我会结合一个有关图片存储的实战案例来讲解。除此之外,这条原则还很容易被过度应用,比如为每一个实现类都定义对应的接口。针对这类问题,在今天的讲解中,我也会告诉你如何来做权衡,怎样恰到好处地应用这条原则。
话不多说,让我们正式开始今天的学习吧!

如何解读原则中的“接口”二字?

“基于接口而非实现编程”这条原则的英文描述是:“Program to an interface, not an implementation”。我们理解这条原则的时候,千万不要一开始就与具体的编程语言挂钩,局限在编程语言的“接口”语法中(比如 Java 中的 interface 接口语法)。这条原则最早出现于 1994 年 GoF 的《设计模式》这本书,它先于很多编程语言而诞生(比如 Java 语言),是一条比较抽象、泛化的设计思想。
实际上,理解这条原则的关键,就是理解其中的“接口”两个字。还记得我们上一节课讲的“接口”的定义吗?从本质上来看,“接口”就是一组“协议”或者“约定”,是功能提供者提供给使用者的一个“功能列表”。“接口”在不同的应用场景下会有不同的解读,比如服务端与客户端之间的“接口”,类库提供的“接口”,甚至是一组通信的协议都可以叫作“接口”。刚刚对“接口”的理解,都比较偏上层、偏抽象,与实际的写代码离得有点远。如果落实到具体的编码,“基于接口而非实现编程”这条原则中的“接口”,可以理解为编程语言中的接口或者抽象类。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了“基于接口而非实现编程”的重要性以及如何在实际编码中应用这一原则。作者首先解释了“基于接口而非实现编程”原则的含义,强调了将接口和实现相分离,封装不稳定的实现,暴露稳定的接口的重要性。文章指出,这一原则可以降低代码的耦合性,提高代码的扩展性,使代码更加灵活应对未来的需求变化。通过具体的实战案例,文章展示了如何在代码中应用这一原则,以及如何通过重构代码来遵循“基于接口而非实现编程”的原则。作者还提到了“基于抽象而非实现编程”是这一原则的另一种表述方式,强调了抽象是提高代码扩展性、灵活性、可维护性最有效的手段之一。总的来说,本文通过解释原则的含义、重要性以及如何在实际编码中应用,帮助读者更好地理解了“基于接口而非实现编程”的概念。文章还强调了在设计接口时要遵循抽象意识、封装意识、接口意识,不暴露任何实现细节,以及在业务场景中根据实现的稳定性来决定是否需要定义接口。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(306)

  • 最新
  • 精选
  • 👽
    那现在的MVC代码,要求service先写接口,然后再写实现,有必要嘛? 说实话,我一直没看懂这种行为的意义何在。

    作者回复: 确实意义不大

    2019-11-25
    19
    14
  • bearlu
    老师,希望能把示例代码和问题代码也放到Github上。

    作者回复: 👌 我抽空整理一下放上去 https://github.com/wangzheng0822

    2019-11-22
    2
    5
  • 大智
    思考题的话,结合spring的话我觉得应该是初始化一个存储处理类并在使用类中@Autowired即可。初始化哪个类取决于你给哪个存储类进行了初始化

    作者回复: 嗯嗯

    2020-11-23
    2
    4
  • tuyu
    老师, 我今天碰到一个问题, 如果我创建阿里云k8s, 那么参数是很多很多, 根据接口原则, 我不太清楚未来不同云平台创建k8s需要哪些参数, 那我应该怎么做

    作者回复: 这个就没法抽象成接口了,只能每个不同的云平台不同处理了。我们也没法追求在替换云平台时,一点代码都不改。尽量少改动代码就可以了。

    2020-05-09
    4
  • Geek_5a5d9a
    我的想法是对外提供构造函数, 构造不同场景的上传, 例如: public ImageProcessingJob aliyunProcessingJob() { // 设置类的基本属性 // self.imageStore = new AliyunImageStore() } public ImageProcessingJob privateProcessingJob() { // 设置类的属性 // self.imageStore = new PrivateImageStore() }

    作者回复: ������

    2020-11-17
    2
  • Geek_East
    想问个问题,泛型的主要目的是代码复用还是抽象呀?

    作者回复: 代码复用

    2020-05-21
    2
  • 刘小辉
    第一:思考题我觉得可以用SPI! 第二: 抽象类的功能应该远远多于接口。但是定义抽象类的代价是比较高的。因为像java,C#这样的高级语言,是不允许多继承的所以,你在设计一个父类为抽象类的时候,一定得将这个类的子类所有的共同属性和方法都定义出来;但是接口可以不用这样。因为接口是一个方法的集合,一个类可以实现多个接口。所以,你的接口里面只有一个方法,还是两个方法,都是可以的。之后如果还有新的方法,我大不了再设计一个接口就是了。所以说,抽象类的设计必须谨慎,接口的设计很灵活。

    作者回复: ������

    2020-11-27
    1
  • 李二木
    我们在做软件开发的时候,一定要有抽象意识、封装意识、接口意识。越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性、扩展性、可维护性。

    作者回复: 说的没错

    2020-11-24
  • 刘永超
    老师把行业“黑话”讲透彻了,捅破那层窗户纸,不用再纠结于一些基本概念。

    作者回复: 哈哈,爱你

    2020-11-14
  • varotene
    Programming against interface 是不是也是抽象(abstraction)的一种手段?把原来具体的问题或者实现(aliyun或者私有云)抽象成任意的云,然后通过interface来予以描述。 至于什么时候用interface,什么时候不用,感觉也跟什么时候用抽象什么时候不用抽象是一个道理?因为进行抽象是需要成本的, 但不需要的时候,我们就可以略过,节省工程成本(YAGNI原则)。这么理解对吗?

    作者回复: 理解的没问题~ 基于接口而非实现是一种抽象的思维

    2020-01-06
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部