什么是接口(What)

百度说:接口泛指实体把自己提供给外界的一种抽象化物,用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式。

牛津字典说:Interface: A point where two systems, subjects, organizations, etc. meet and interact.

维基百科说:In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information.

Frank说:上面说的都对,但是关于接口我还有更多想说的。

接口有什么好处(Why)

在我看来,接口在软件设计中主要有两大好处:

1. 制定标准

标准规范的制定离不开接口,制定标准的目的就是为了让定义和实现分离,而接口作为完全的抽象,是标准制定的不二之选。

这个世界的运转离不开分工协作,而分工协作的前提就是标准化。试想一下,你家的电脑能允许你把显卡从NVIDIA换成七彩虹;你家的灯泡坏了,你可以随便找一个超市买一个新的就可以换上;你把数据从Oracle换成了MySQL,但是你基于JDBC写的代码都不用动。等等这些事情的背后都是因为接口,以及基于接口定制的标准化在起作用。

在Java的世界里,有一个很NB的社区叫JCP( Java Community Process),就是专门通过JSR(Java Specification Request)来制定标准的。正是有了JSR-315(Java Servlet),我们服务端的代码才能在Tomcat和Jetty之间自由切换。

最后,我想用一句话来总结一下标准的重要性,那就是:“一流的企业做标准,二流的企业做品牌,三流的企业做产品。

2. 提供抽象

除了标准之外,接口还有一个特征就是抽象。正是这样的抽象,得以让接口的调用者和实现者可以完全的解耦。

解耦的好处是调用者不需要依赖具体的实现,这样也就不用关心实现的细节。这样,不管是实现细节的改动,还是替换新的实现,对于调用者来说都是透明的。

这种扩展性和灵活性,是软件设计中,最美妙的设计艺术之一。一旦你品尝过这种“依赖接口”的设计来带的美好,就不大会再愿意回到“依赖实现”的简单粗暴。平时我们说的“面向接口编程原则”和“依赖倒置原则”说的都是这种设计

另外,一旦你融会贯通的掌握了这个强大的技巧——面向抽象、面向接口,你会发现,虽然面向实现和面向接口在代码层面的差异不大,但是其背后所隐含的设计思想和设计理念的差异,不亚于我篮球水平和詹姆斯篮球水平之间的差异!

    //面向接口Animal dog = new Dog();//面向实现Dog dog = new Dog();

作为一名资深职场老兵,我墙裂建议各位在做系统设计、模块设计、甚至对象设计的时候。要多考虑考虑更高层次的抽象——也就是接口,而不是一上来就陷入到实现的细节中去。要清楚的意识到接口设计是我们系统设计中的主要工作内容。而这种可以跳出细节内容,站在更高抽象层次上,来看整个系统的模块设计、模块划分、模块交互的人,正是我们软件设计队伍中,非常稀缺的人才。有时候,我们也管这些人叫架构师

什么时候要用接口(When)

有扩展性需求的时候

可扩展设计,主要是利用了面向对象的多态特性,所以这里的接口是一个广义的概念,如果用编程语言的术语来说,它既可以是Interface,也可能是Abstract Class。

这种扩展性的诉求在软件工作中可以说无处不在,小到一个工具类。例如,我现在系统中需要一个开关的功能,开关的配置目前是用数据库做配置的,但是后续可能会迁移到Diamond配置中心,或者SwitchCenter上去。

简单做法就是,我直接用数据库的配置去实现开关功能,如下图所示:

但是这样做的问题很明显,当需要切换新的配置实现的话,就不得不扒开原来的应用代码做修改了。更恰当的做法应该是提供一个Switch的接口,让不同的实现去实现这个接口,从而在切换配置实现的时候,应用代码不再需要更改了。

如果说,上面的重构只是使用策略模式对代码进行了局部优化,做了当然更好,不做的话,影响也还好,可以将就着过。

那么接下来我要给大家介绍的场景,就不仅仅是“要不要”的问题,而是“不得不”的问题了。

例如,老板给你布置了一个任务,实现一个类似于eclipse可以可插拔(Pluggable)的产品,此时,使用接口就不仅仅是一个选择问题了,而是你不得不使用的架构方法了。因为,可插拔的本质就是,你制定一个标准接口(API),然后有不同的实现者去做插件的实现,最后再由PluginManager把这个插件机制串起来而已。

下图是我当时给ICBU设计的一个企业协同云的Pluggable架构,其本质上,也就是基于接口的一种标准和扩展的设计。

需要解耦的时候

上面介绍的关于Switch的例子,从表面上来看,是扩展性的诉求。但不可扩展的本质原因正是因为耦合性。当我们通过Switch Interface来解开耦合之后,扩展性的诉求也就迎刃而解了。

发现这种耦合性,对系统的可维护性至关重要。有一些耦合比较明显(比如Switch的例子)。但更多的耦合是隐式的,并没有那么明显,而且在很长一段时间,它也不是什么问题,但是,一旦它变成一个问题,将是一个非常头痛的问题。

一个真实的典型案例,就是java的logger,早些年,大家使用commons-logging、log4j并没有什么问题。然而,此处一个隐患正在生长——那就是对logger实现的强耦合。

当logback出来之后,事情开始变得复杂,当我们想替换一个新的logger vendor的时候,为了尽量减少代码改动,不得不上各种Bridge(桥接),到最后日志代码变成了谁也看不懂的代码迷宫。下图就是我费了九头二虎之力,才梳理清楚的一个老业务系统的日志框架依赖情况。

试想一下,假如一开始我们就能遇见到这种紧耦合带来的问题。在应用和日志框架之间加入一层抽象解耦。后续的那么多桥接,那么多的向后兼容都是可以省掉的麻烦。而我们所要做的事情,实际上也很简单——就是加一个接口做解耦而已(如下图所示)

要给外界提供API的时候

上文已经介绍过JCP和JSR了,大家有空可以去阅读一些JSR的文档。不管是做的比较成功的JSR-221(JDBC规范)、JSR-315(Servlet规范),还是比较失败的JSR-94(规则引擎规范)等等。其本质上都是在定义标准、和制定API。其规范的内容都是抽象的,其对外发布的形式都是接口,它不提供实现,最多会指导实现

还有就是我们通常使用的各种开放平台的SDK,或者分布式服务中RPC的二方库,其包含的主要成分也是接口,其实现不在本地,而是在远程服务提供方。

类似于这种API的情况,都是在倒逼开发者要把接口想清楚。我想,这也算微服务架构一个漂亮的“副作用”吧。当原来单体应用里的各种耦合的业务模块,一旦被服务化之后,就自然而然的变成“面向接口”的了。

通过依赖倒置来实现面向接口(How)

关于依赖倒置,我以前写过不少文章,来阐述它的重要性。实际上,我上面给出的关于扩展需求的Switch案例,关于解耦的logger案例。其背后用来解决问题的方法论都是依赖倒置


如上图所示,依赖倒置原则主要规定了两件事情:

  1. 高层模块不应该依赖底层模块,两者都应该依赖抽象(如上面的图2所示)
  2. 抽象不应该依赖细节,细节应该依赖抽象。

我们回头看一下,不管是Switch的设计,还是抽象Logger的设计,是不是都在遵循上面的两条定义内容呢。

实际上,DIP(依赖倒置原则)不光在对象设计,模块设计的时候有用。在架构设计的时候也非常有用,比如,我在做COLA 1.0的时候,和大多数应用架构分层设计一样,默许了Domain层可以依赖Infrastructure层。

这种看起来“无伤大雅”的设计,实际上还是存在不小的隐患,也违背了我当初想把业务复杂度和技术复杂度分开的初心,当业务变得更加复杂的时候,这种“偷懒”行为很可能会导致Domain层堕落成大泥球(Big mud ball)。因此,在COLA 2.0的时候,我决定用DIP来反转Domain层和Infrastructure层的关系,最终形成如下的结构:

这样做的好处是Domain层会变得更加纯粹,其好处体现在以下三点:

1、解耦: Domain层完全摆脱了对技术细节(以及技术细节带来的复杂度)的依赖,只需要安心处理业务逻辑就好了。

2、并行开发: 只要在Domain和Infrastructure约定好接口,可以有两个同学并行编写Domain和Infrastructure的代码。

3、可测试性: 没有任何依赖的Domain里面都是POJO的类,单元测试将会变得非常方便,也非常适合TDD的开发。

什么时候不需要接口

"劲酒虽好,可不要贪杯哦!"

和许多其它软件原则一样,面向接口很好,但也不应该是不分背景、不分场合胡乱使用的杀手锏和尚方宝剑。因为过多的使用接口,过多的引入间接层也会带来一些不必要的复杂度。

比如,我就看过有些应用的内部模块设计的过于“灵活”,给什么DAO、Convertor都加上一层Interface,但实际情况是,应用中对DAO、Convertor的实现进行替换的可能性极低。类似于这样的,装模作样,装腔作势的Interface就属于可有可无的鸡骨头(比鸡肋还低一个档次)。

就像《Effective Java》的作者Joshua Bloch所说:

“同大多数学科一样,学习编程的艺术首先要学会基本的规则,然后才能知道什么时候可以打破这些规则。”

关于面向接口编程,你真的弄懂了吗?相关推荐

  1. 面向接口编程VS《倚天屠龙记》里张三丰教无忌打太极

    搞笑哈,只细想想,编程和太极怎么能联系在一起了,是八秆子也打不着的哈! 昨天看了一篇文章是关于面向接口编程的文章,颇有心得,其实在今天中国IT软件行业的盛行,程序员们突飞猛涨,真正算的上程序员的又有几 ...

  2. go 学习笔记之万万没想到宠物店竟然催生出面向接口编程?

    到底是要猫还是要狗 在上篇文章中,我们编撰了一则简短的小故事用于讲解了什么是面向对象的继承特性以及 Go 语言是如何实现这种继承语义的,这一节我们将继续探讨新的场景,希望能顺便讲解面向对象的接口概念. ...

  3. golang与面向接口编程

    这节不阐述OOP的理念,从接口直接讲,需要一定的抽象思想,新手可以绕道 go里面的接口定义 Go语言不同于其他语言.在Go语言中,接口是自定义类型,用于指定一组一个或多个方法签名,并且该接口是抽象的, ...

  4. 【转】工厂模式面向接口编程

    为了实现更好的灵活性     应改面向接口编程.因此,应该面向接口提供工场.         比如,Cat,   Dog,   Mouse,都是4条腿会跑的动物.     因此,我们建立一个接口叫做F ...

  5. 黑马java教程是什么_Java教程:揭秘什么是面向接口编程

    先用一个案例来给大家说明一下面向接口编程. 案例:有一个电脑类(Computer),电脑除了有基本的开机关机功能外,还有连接任何外接设备的功能,比如能电脑能连接外置键盘(Keyboard),鼠标(Mo ...

  6. Java面向接口编程,低耦合高内聚的设计哲学

    接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极大的降低程序中各个模块之间的耦合,提高系统的可维护性以及可扩展性. 因此,很多的软件架构设计理念都倡导"面向接口编程"而 ...

  7. java的知识点13——多态、对象的转型(casting)、final关键字、抽象方法和抽象类、接口的作用、如何定义和使用接口?、接口的多继承、面向接口编程

    多态 多态指的是同一个方法调用,由于对象不同可能会有不同的行为.现实生活中,同一个方法,具体实现会完全不同. 多态的要点: 1. 多态是方法的多态,不是属性的多态(多态与属性无关). 2. 多态的存在 ...

  8. Java 面向抽象编程和面向接口编程

    以下内容来自<Java 2实用教程>,主编:耿祥义.张跃平 鉴于面向抽象编程和面向接口编程思维培养的重要性,写此博客巩固. 面向抽象编程: 在设计程序时,经常会使用到abstract类,其 ...

  9. 为什么有人说面向对象编程就是面向接口编程?

    "面向对象编程就是面向接口编程" 这句话相信, 很多人都在网上见过, 装b利器. 我一开始也是这么想的, 那些装b者丢下这一句, 就没下文了. 首先, 我认为这句话是1个假命题. ...

  10. python面向接口编程_Python 中的面向接口编程

    前言 "面向接口编程"写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性.维护性谁都不能拒绝 ...

最新文章

  1. nodejs这个过程POST求
  2. 如何在RHEV平台中新建ISO存储域
  3. perl大骆驼和小骆驼_快速的骆驼和云消息传递
  4. linux学习交流群,求linux(ubuntu)学习交流群
  5. FPGA不积跬步(目录篇)
  6. 关于二分限制最短路的题的总结
  7. mysql分表和表分区详解
  8. 地址栏js的写法(转载)
  9. 高级商务办公软件应用【14】
  10. HaaS EDU场景式应用学习 - 光照信息屏
  11. 基于单片机的电子琴设计和硬件平台设计
  12. 360宽带测速至少在我的网络环境里有设计缺陷
  13. 为什么mysql填不了数据库_求助,为何我的数据不能写入数据库
  14. 手把手教你使用微软官方文件免费恢复神器Windows File Recovery恢复文件
  15. uploadifive struts2实现图片上传
  16. win10退出当前guest用户
  17. linux 汇编 读取软盘,学习x86汇编语言7 使用INT13读取软盘数据
  18. php 小程序服务商支付模式
  19. 软件视频会议性能测试要点,IP网络视频会议系统中MCU性能测试方法的研究
  20. mysql数据库忘记root密码

热门文章

  1. DM manager工具使用
  2. 苹果Mac突然没有声音,3 种方法快速检测
  3. 面试想不带简历,老罗可以,你不行!
  4. 互联网行业,常见含金量高的证书,看看你有几个?
  5. 神奇网盘搜索 只搜网盘不搜其它 一键搜索所有网盘资源
  6. ClientKey实现登录QQ空间,并设置背景音乐
  7. geektool 天气_桌面自定义:适用于OS X的GeekTool简介
  8. 基于医院信息管理系统案例的软件构造分析
  9. Homekit直连的灯带控制套装
  10. 电子管:6J1基本特性文献调研