我记得我曾经在一篇帖子中提到过,一个接口可以从三方面去考察:
制定者(或者叫协调者),实现者(或者叫生产者),调用者(或者叫消费者)。
接口本质上就是由制定者来协调实现者和调用者之间的关系。
所以通常说的“面向接口编程”可以理解为:
只有实现者和调用者都遵循“面向接口编程”这个准则,制定者的协调目的才能达到。
在项目中的意义:
在传统的项目开发过程中,由于客户的需求经常变化,如果不采用面向接口编程,那么我们必须不停改写现有的业务代码。改写代码可能产生新的BUG,而且改写代码还会影响到调用该业务的类,可能全都需要修改,影响系统本身的稳定性。而且为了将改写代码带来的影响最小,我们不得不屈服当前的系统状况来完成设计,代码质量和稳定性更低。当这种情况积累到一定程度时,系统就会出现不可预计的错误,代码凌乱,不易读懂,后接手的人无法读懂代码,系统的维护工作越来越重,最终可能导致项目失败。
接口在项目就是一个业务逻辑,面向接口编程就是先把客户的业务提取出来,作为接口。业务具体实现通过该接口的实现类来完成。当客户需求变化时,只需编写该业务逻辑的新的实现类,通过更改配置文件(例如Spring框架)中该接口的实现类就可以完成需求,不需要改写现有代码,减少对系统的影响。
采用基于接口编程的项目,业务逻辑清晰,代码易懂,方便扩展,可维护性强。即使更换一批人员,新来的人依然可以快速上手。对于公司来说,意义更大。
在Java中的意义:
Java本身也是一个不断完善的语言,他也在频繁的改动他的系统API来完善,他的API是一个庞大的体系,互相关联,如果不采用接口,而都是用实现类的话,那么API的改动就会给整个体系带来不稳定。而且如果改动API,那么就会有大量采用旧API的项目因无法正常运行,会损失大量客户。换句话说,JDK已经发布的API是一种承诺,一经发布就不能更改,即使原来API存在各种各样的问题(例如java.util.Properties类就是一个失败的例子)也必须保留,于是在Java里就出现了不建议使用的方法,但JDK依然提供该方法。而且Java语言本身是一个跨平台的语言,为了满足在各个平台下运行,就必须把各种操作做成接口,在编写各个平台下的实现类。
设计模式的体现:
在设计模式的原则里的开闭原则,其实就是要使用接口来实现对扩展开放,对修改关闭。在设计模式的其他原则里也有关于基于接口编程的原则,即依赖倒转的设计原则(DIP)----高层模块不应该依赖于底层模块。二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象(注:来自《敏捷软件开发--原则、模式与实践》Robert C.Martin著)。在使用面向接口的编程过程中,将具体逻辑与实现分开,减少了各个类之间的相互依赖,当各个类变化时,不需要对已经编写的系统进行改动,添加新的实现类就可以了,不在担心新改动的类对系统的其他模块造成影响。
编程也是一门艺术,在C语言中灵活的使用指针是一门艺术,在面对对象的程序中,灵活的使用接口也是一门艺术。现在项目中,功能越来越复杂,只设计了完美的类,对于整个系统来说没有多大意义,现在的项目更注重各个功能模块的整合及可维护性,接口的设计就显得更为重要了。程序设计不再是设计类的具体实现,而是从整个项目出发,设计出可扩展性强的接口。当你发现越来越灵活的使用接口时,那么你就从程序员升级为架构师了。可惜我现在依然是一名程序员,正在像架构师努力。
在一些大型项目或者大型公司里,都是由架构师编写出系统接口,具体的实现类交给了程序员编写,公司越大这种情况越明显,所以在这些公司里做开发,我们可能都不知道编写出的系统是个什么样子,每天做的工作可能就是做“填空题”了。建议大家阅读敏《捷软件开发--原则、模式与实践》Robert C.Martin著这本书,那么对如何进行接口编程就会有一个新的认识了。
最后,希望大家都能成为一个优秀的系统架构师。
接口 = 电脑的USB插口!
因为接口订好了,所以那面到底插的是什么就不重要了!
我们用户只需要
1 插上去
2 停用移动设备
3 拔下来
这三个就好似USB的接口功能。他隐藏了实际功能,但提供给用户统一的操作界面和使用方式
项目开发中绝对会碰到接口,但是为什么要使用接口成了绝大多数java程序员的疑问,为什么一定要写个没有实现任何功能的只有几个方名的类,可能也有一些人明白接口就是好,但好在哪里很难解释出来,我当初也是这样想的,但是当我一瞬间觉悟后发现这种想法很幼稚。OOP的四大基本特征 多态 继承 封装 抽象 全与接口有关,可以说不懂接口的人完全不懂OOP是什么,更不用说能做出好项目,所以对接口的理解很重要。讲接口之前再讲一样东西,它与接口是密不可分的,这两者必须要一起讲才行,那就是依赖注入(控制反转)。
spring的核心思想之一,又有人有疑惑了,这东西很麻烦,还要在配置文件中配来配去,直接new一个不是挺好用的吗,多省事啊。
1依赖注入从编程方面讲提高了效率,在系统启动时容器将除去业务逻辑(因为业务不是时时刻刻都会用到的)以外的一大部分方法加载到内存中,一个请求过来时你要哪个方法我从内存中给你哪个方法,而new的时候是需要在内存中分出一点空间来放你new出来的东西,一百个请求new一百次,一亿个请求new一亿次。
2依赖注入从设计模式上来讲提高了解耦性,重用性,与传统的new,一个是给一个是拿(用控制反转来理解这句话)。举例:你要一辆车,自己造一辆(new)。依赖注入像汽车中心(容器)买或者租一辆.自己造要花时间造,汽车场给钱立马给你。如果你就开一次,自己造完了用了一次丢那里浪费了,汽车场租一辆,用完就还回去,别人还能用。可能你又会想,自己造的别人也还能用啊,但那只限于知道你有辆车的人,但只要是人都知道汽车场有汽车。
讲完依赖注入就可以讲接口了。接口的基本特征就不多说了,下面来讲接口到底好在哪
一.目录
开发一个项目中,总是需要互相调用一些功能的,比如业务组开发人员需要技术组提供一些实用的方法,那么就出现了两种情况。
1.不使用接口,直接写。
当你需要去看看这个类有什么你需要的方法时,你看到的是一大堆的代码,悲剧了,几千行代码,有的方法几百行有的方法一两行,哪个是我要的方法呢,一个个找吧,更悲剧者碰上编码习惯不好的,不管是外部方法还是内部封装一下的小方法的修饰名全都用Public,找晕你。
2使用接口
接口没有任何的实现,只有方法名,一排一排很有规则的看下去,我不需要去看他的实现过程,我只需要知道这我想要的达到的目的通过哪个方法能实现,至于他的过程本来就不需要我来考虑。
举例:你买了本hibernate编程思想,你想要知道怎么配置hibernate的参数。翻开一看,蛋疼,没有目录,你就一页一页翻吧,翻的同时还得看清楚点,别翻过头了。
二.变更
开发项目中,不免会有一些大的变更,甚至于上线之后都有可能,那么一些影响全局的变更就出现了。比如数据库本来用的是MySql,变态的需求突然说要换成oracle。
1 没有使用接口开发
写一个新的类,把所有调用的全改掉,因为类型都不对了。
2 使用接口的类
只需要在写一个SQL接口的实现类,在配置文件中修改一下注入的路径,搞定。
有人又会说直接改那个内的方法不就可以了,那我需求再变态一下,白天用MySql晚上用oracle,那是否你所有操作数据库之前都要if(白天)else if(晚上)?而接口只需要容器支持将注入的实现类换一个就行了,因为实现类必须实现接口的所有抽象方法,所以在编译时是能通过的。
举例:一个医院有一个口腔部门,口腔部门里有一位医生叫王医生,通过写死的看法我如果要去看病就是找这个王医生,一天王医生不干了,来了一个刘医生,完了我只能看王医生的,这可能吗 ?通过接口来看医院是接口他能治病,口腔部门是医院的子类,明确到了是治疗口腔的,医生是实现类,他能治口腔病,至于这个医生叫什么,关我屁事,我只要知道你有治病这个方法就行了。
三.扩展性
最近工作太轻松,闲来无聊做了个练习小项目,这个项目除了必要的DOM4J和JDBC没用一个jar包,前言说完了,说说我的做法。项目启动时先加载自己做的容器,然后加载DB、Log等接口、最后加载service、action,刚开始我在加载容器后就直接按顺序把DB配置文件加载好生成一个DBService丢到数据总线中,然后加载LOG同样的做法。考虑了很久发现这种做法有点问题,后来改成这样了,容器无非就是管理接口类的东西,我就又写了个抽象类(因为抽象类可以有成员变量)一个抽象方法initService 两个成员变量 HashMap serviceMap
HashMap serviceDataMap 一个存service 一个存它可能会附带的一些数据,我现在只需要写实现类 在initService 方法中加载XML 将该Service初始化好 丢到serviceMap中就哦了,这样做的好处就是,无论我以后有多少插件配置文件配一个实现类,写一个实现类,方法中加载一些东西,丢到父类的serviceMap中,以后所有的类注入都能注入该service。
四.结构化
一个项目的好坏就要看他的结构是否清晰,java规定了类只能单一继承,是为了避免错综复杂的关系,在很多文章中都提到过类的继承是项目中的一颗地雷,而接口没有实现过程,只有表明是干什么的,所以就算多继承(接口可以继承多个接口),结构还是很清晰的。
自我总结出就这四个优点很明显,看别人的文章说的最多的还有一个好处开发中使用,我觉得很恶心,实现屁没写方法一大堆,写完一大堆的方法后,去写实现时突然发现又要加个新方法才行或者写好的那个方法又没啥用,要删掉,最后搞的你心思无限宽广,有时候开发过程想太多太远是没好处的,可能写的过程中又会出现很多其他的想法,因为我们是人,不是CPU,运行的不是那么准确,当然几乎每个架构师技术都很牛X,估计也是有人能做到这一点的,但是做不到的还是慢慢来,都写好了再弄个接口或抽象类。
最后总结一点 接口就是你需要什么就调什么 完完全全的封装 不用考虑你的实现过程 连类名都可以忽略 你只要告诉容器 我需要的是哪种类型的接口就行了。
优点:
接口和实现分离了,适于团队的协作开发。
更具体的优点:可以参看IDP原则。
缺点:
设计难了,在你没有写实现的时候,就得想好接口,接口一变,全部乱套,这就是所谓的设计比实现难。