1.面向接口~程和面向对象编E是什么关p?/strong>
首先Q面向接口编E和面向对象~程q不是^U的Q它q不是比面向对象~程更先q的一U独立的~程思想Q而是附属于面向对象思想体系Q属于其一部分。或者说Q它是面向对象编E体pM的思想_N之一?/p>
2.接口的本?/strong>
接口Q在表面上是由几个没有主体代码的Ҏ定义l成的集合体Q有唯一的名Uͼ可以被类或其他接口所实现Q或者也可以说承)。它在Ş式上可能是如下的样子Q?/p>
那么Q接口的本质是什么呢Q或者说接口存在的意义是什么。我认ؓ可以从以下两个视角考虑Q?/p>
1Q接口是一l规则的集合Q它规定了实现本接口的类或接口必L有的一l规则。体C自然?#8220;如果你是……则必能……”的理c?/strong>
例如Q在自然界中Qh都能吃饭Q即“如果你是人,则必能吃饭”。那么模拟到计算机程序中Q就应该有一个IPersonQ习惯上Q接口名?#8220;I”开_接口Qƈ有一个方法叫Eat()Q然后我们规定,每一个表C?#8220;?#8221;的类Q必d现IPerson接口Q这模拟了自然?#8220;如果你是人,则必能吃饭”q条规则?/p>
从这里,我想各位也能看到些许面向对象思想的东ѝ面向对象思想的核心之一Q就是模拟真实世界,把真实世界中的事物抽象成c,整个E序靠各个类的实例互盔R信、互相协作完成系l功能,q非常符合真实世界的q行状况Q也是面向对象思想的精髓?/p>
2Q接口是在一定粒度视图上同类事物的抽象表C。注意这里我了在一定粒度视图上Q因?#8220;同类事物”q个概念是相对的Q它因ؓ_度视图不同而不同?/strong>
例如Q在我的眼里Q我是一个hQ和一头猪有本质区别,我可以接受我和我同学是同c这个说法,但绝不能接受我和一头猪是同cR但是,如果在一个动物学家眼里,我和猪应该是同类Q因为我们都是动物,他可以认?#8220;?#8221;?#8220;?#8221;都实CIAnimalq个接口Q而他在研I动物行为时Q不会把我和猪分开对待Q而会?#8220;动物”q个较大的粒度上研究Q但他会认ؓ我和一|有本质区别?/p>
现在换了一个遗传学Ӟ情况又不同了Q因为生物都能遗传,所以在他眼里,我不仅和猪没区别Q和一只蚊子、一个细菌、一颗树、一个蘑菇乃至一个SARS病毒都没什么区别,因ؓ他会认ؓ我们都实CIDescendableq个接口Q注Qdescend vi. 遗传Q,x们都是可遗传的东西,他不会分别研I我们,而会所有生物作为同c进行研IӞ在他眼里没有人和病毒之分Q只有可遗传的物质和不可遗传的物质。但臛_Q我和一块石头还是有区别的?/span>
可不q的事情发生了,某日Q地球上出现了一位伟大的人,他叫列宁Q他在熟读马克思、恩格斯的辩证唯物主义思想巨著后,颇有心得Q于是他下了一个著名的定义Q所谓物质,是能被意识所反映的客观实在。至此,我和一块石头、一丝空气、一条成语和传输手机信号的电场已经没什么区别了Q因为在列宁的眼里,我们都是可以被意识所反映的客观实在。如果列宁是一名程序员Q他会这么说Q所谓物质,是所有同时实C“IReflectabe”?#8220;IEsse”两个接口的类所生成的实例。(注:reflect v. 反映 esse n. 客观实在Q?/span>
也许你会觉得我上面的例子像在瞎掰Q但是,q正是接口得以存在的意义。面向对象思想和核心之一叫做多态性,什么叫多态性?说白了就是在某个_度视图层面上对同类事物不加区别的对待而统一处理。而之所以敢q样做,是因ؓ有接口的存在。像那个遗传学家Q他明白所有生物都实现了IDescendable接口Q那只要是生物,一定有DescendQ)q个ҎQ于是他可以统一研究Q而不至于分别研究每一U生物而最l篏歅R?/span>
可能q里q不能给你一个关于接口本质和作用的直观印象。那么在后文的例子和对几个设计模式的解析中,你将会更直观体验到接口的内涵?/span>
3.面向接口~程lD
通过上文Q我惛_家对接口和接口的思想内涵有了一个了解,那么什么是面向接口~程呢?我个人的定义是:在系l分析和架构中,分清层次和依赖关p,每个层次不是直接向其上层提供服务Q即不是直接实例化在上层中)Q而是通过定义一l接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体c?/span>?/strong>
q样做的好处是显而易见的Q首先对pȝ灉|性大有好处。当下层需要改变时Q只要接口及接口功能不变Q则上层不用做Q何修攏V甚臛_以在不改动上层代码时下层整个替换掉Q就像我们将一个WD?0G盘换成一个希L160G的硬盘,计算机其他地方不用做M改动Q而是把原盘拔下来、新盘插上p了,因ؓ计算机其他部分不依赖具体盘Q而只依赖一个IDE接口Q只要硬盘实Cq个接口Q就可以替换上去。从q里看,E序中的接口和现实中的接口极为相|所以我一直认为,接口QinterfaceQ这个词用的真是似Q?/span>
使用接口的另一个好处就是不同部件或层次的开发h员可以ƈ行开工,像造硬盘的不用{造CPU的,也不用等造显C器的,只要接口一_设计合理Q完全可以ƈ行进行开发,从而提高效率?/span>
本篇文章先到q里。最后我惛_啰嗦一句:面向对象的精髓是模拟现实Q这也可以说是我q篇文章的灵。所以,多从现实中思考面向对象的东西Q对提高pȝ分析设计能力大有脄?/span>
下篇文章Q我用一个实例来展示接口~程的基本方法?/span>
而第三篇Q我解析经典设计模式中的一些面向接口编E思想Qƈ解析一?NET分层架构中的面向接口思想?/span>
Ҏ文的补充Q?/strong>
仔细看了各位的回复,非常高兴能和大家一赯论技术问题。感谢给定的朋友Q也要感谢提出意见和质疑的朋友,q促使我更深入思考一些东西,希望能借此q步。在q里我想补充一些东西,以讨Z些回复中比较集中的问题?/span>
1.关于“面向接口~程”中的“接口”与具体面向对象语a?#8220;接口”两个?/strong>
看到有朋友提?#8220;面向接口~程”中的“接口”二字应该比单U编E语a中的interface范围更大。我l过思考,觉得很有道理。这里我写的实不太合理。我惻I面向对象语言中的“接口”是指具体的一U代码结构,例如C#中用interface关键字定义的接口。?#8220;面向接口~程”中的“接口”可以说是一U从软g架构的角度、从一个更抽象的层面上指那U用于隐藏具体底层类和实现多态性的l构部g。从q个意义上说Q如果定义一个抽象类Qƈ且目的是Z实现多态,那么我认为把q个抽象cMUCؓ“接口”是合理的。但是用抽象cd现多态合理不合理Q在下面W二条讨论?/span>
概括来说Q我觉得两个“接口”的概忉|怺区别又相互联pR?strong style="margin: 0px; padding: 0px;">“面向接口~程”中的接口是一U思想层面的用于实现多态性、提高Y件灵zL和可维护性的架构部gQ而具体语a中的“接口”是将q种思想中的部g具体实施C码里的手Dc?/span>
2.关于抽象cM接口
看到回复中这是讨论的比较Ȁ烈的一个问题。很抱歉我考虑不周没有在文章中讨论q个问题。我个h对这个问题的理解如下Q?/span>
如果单从具体代码来看Q对q两个概念很Ҏ模糊Q甚臌得接口就是多余的Q因为单从具体功能来看,除多重承外QC#QJava中)Q抽象类g完全能取代接口。但是,N接口的存在是Z实现多重l承Q当然不是?span style="margin: 0px; padding: 0px; color: #ff0000; line-height: 19px;">我认为,抽象cd接口的区别在于用动机。用抽象类是ؓ了代码的复用Q而用接口的动机是ؓ了实现多态性?/strong>所以,如果你在为某个地方该使用接口q是抽象c而犹豫不xQ那么可以想想你的动机是什么?/span>
看到有朋友对IPersonq个接口的质疑,我个人的理解是,IPersonq个接口该不该定义,关键看具体应用中是怎么个情c如果我们的目中有Women和ManQ都l承PersonQ而且Women和Manl大多数Ҏ都相同,只有一个方法DoSomethingInWCQ)不同Q例子比较粗俗,各位见谅Q,那么当然定义一个AbstractPerson抽象cL较合理,因ؓ它可以把其他所有方法都包含q去Q子cd定义DoSomethingInWCQ)Q大大减了重复代码量?/span>
但是Q如果我们程序中的Women和Man两个cd本没有共同代码,而且有一个PersonHandlec需要实例化他们Qƈ且不希望知道他们是男是女Q而只需把他们当作h看待Qƈ实现多态,那么定义成接口就有必要了?/span>
总而言之,接口与抽象类的区别主要在于用的动机Q而不在于其本w。而一个东西该定义成抽象类q是接口Q要Ҏ具体环境的上下文军_?/span>
再者,我认为接口和抽象cȝ另一个区别在于,抽象cd它的子类之间应该是一般和Ҏ的关p,而接口仅仅是它的子类应该实现的一l规则。(当然Q有时也可能存在一般与Ҏ的关p,但我们用接口的目的不在q里Q如Q交通工具定义成抽象c,汽R、飞机、轮船定义成子类Q是可以接受的,因ؓ汽R、飞机、轮舚w是一U特D的交通工兗再譬如Icomparable接口Q它只是_实现q个接口的类必须要可以进行比较,q是一条规则。如果Carq个cdCIcomparableQ只是说Q我们的Car中有一个方法可以对两个Car的实例进行比较,可能是比哪辆车更贵,也可能比哪辆车更大,q都无所谓,但我们不能说“汽R是一U特D的可以比较”Q这在文法上都不通?/span>