转自:http://www.360doc.com/content/13/1114/11/10504424_329106146.shtml
不管以前你是否据说过面向接口,本文所描述的将是一个全新的设计思想叫面向接口。这里的接口并非代码中的 interface 关键字,思想和语言是没有直接关系的,只不过有些语言实现一种思想比较方便而已。
在了解面向接口前,必须先了解面向对象,由于面向接口是从面向对象根据历史的经验衍生出来的一种思想。在面向对象中,一切都是对象,对象拥有独立性:它必须保持一个内部状态,而且避免一切外界干扰。因此面向对象要求大部分字段都应该私有的,而后提供有限的公开的接口去访问这些字段。如:
复制代码
class 书 {
private string 名字;
public string get名字(){
return this.名字;
}
}
复制代码
初学者常常会问:为何不直接公开这个字段,必定要写个get名字的函数才能获取到书的名字。面向对象的专家会回答这是为了类的封装性(即独立性)。名字这个字段对外界来讲是只读不可写的。
面向对象经过强调对象的独立性保证了高的代码重用率,下降了类的学习成本(无需关心内部细节)。可是它却忘了一个事实:世界万物都有联系。因而,当两个对象开始有联系时,麻烦的问题就出现了。好比如今新增一我的的类:
复制代码
class 人 {
public void 读书(书 a){
读取( a.get名字() )
}
}
复制代码
人能够读书,但书也能够被读。那么读书这个操做是属于人仍是属于书,在面向对象中是没有区分的。虽然书自己是一个独立的对象,可是人在读书时,却又不得不打破书的封装性----人须要读取书的内容和更多细节。抓着封装思想不放,就不得不为书增长API才能让书真正被读:一个对象提供哪些API是根据需求来决定的。若是需求不少,那么书的API会很是多,当其余人去读这份源码时,会发现原本一个很简单的对象,却有不少不知道干吗用的API。不少API是为了某些需求而写的,做者将它们塞进这个对象,仅仅为了更方便访问私有字段。这种代码设计其实已经偏离了面向对象的初衷,但对做者而言,完成项目才是重点。因此他们选择这种折中的方式:API随便加,反正达到访问的目标便可,打破了封装又如何?因此也有人说:只有有专家才会在一开始就设计好有哪些对象和API,才能写出真正面向对象的代码,这些专家被称为软件构架师。面向对象拒而不谈对象之间的联系,致使一开始好好的代码最后变成互相引用的难以维护的代码。
关于更多面向对象的缺陷,能够见另外一篇文章:《面向对象中的设计陷阱》
接下来介绍面向接口。面向接口中,一样的一切都是对象,可是它将对象分红两类:生物和非生物。非生物就是没有生命的对象:好比一本书,一个电脑。在程序中,非生物老是被动的----好比球本身是不会飞的,它只能被踢飞。生物则表明能力的拥有者,它能够处理非生物,能够记忆,能够和其它生物沟通。
好比现实场景:小明的电脑坏了,而后它交给小刚去修。这里其实有三个对象:小明、小刚、电脑。是人都知道:小明和小刚是生物,电脑是非生物。小明须要作这些事情:1. 记住他有一台电脑,这是他的私有财产。2. 通知小刚去修电脑,而且将他的私有财产转交给小刚。小刚须要作这些事情:修电脑(不论是谁的电脑)。电脑是非生物,所以它不能作任何事情。那么面向接口中,如何将这个现实问题转换为代码表示呢?
原则一:全部的非生物不具有任何封装性。
以电脑为例,虽然咱们总将电脑当作一个独立的总体,但确实是存在一些时刻,它的零件是打散的。电脑自己没有思考能力,它不能保证本身必定是处于完整的,能用的状态。所以对非生物来讲,它不须要在内部维护一个状态。可是它能够有一些必要保护措施,来确保它不会被闲人弄坏,但这个措施不是强制的。就好像你弄坏了电脑,错在你,不是由于电脑质量差(固然好电脑是不会随便被搞坏的)。
原则二:全部的生物具备封装性。
好比小明拥有的电脑是他的私有财产,除非他愿意,不然没人可使用他的电脑。若是小明主动忘记了他有一台电脑,那么这台电脑和小明将失去任何联系。
原则三:对事不对人。
好比小明的电脑坏了,他不必定就得交给小刚作,他只要交给一个会修电脑的人来作就行,只不过恰好小刚符合要求而已。
总结如上原则,上述现实问题描述成代码应该是这样的:
复制代码
class 电脑{
public bool 还的仍是坏的;
}
class 小明{
private 电脑 a;
public void 去修电脑(会修电脑的人 b){
b.修电脑(a);
}
}
class 小刚 : 会修电脑的人{
public void 修电脑(电脑 a) {
a.还的仍是坏的 = true;
}
}
复制代码
以上代码和面向对象代码的区别:
1. 电脑拥有 public 字段:由于电脑是非生物,不须要封装。
2. 去修电脑的参数是会修电脑的人,而不是小刚。
原则四:能力能够随时扩展。
以上三个原则其实并未体现面向接口的优点,真正的优点在于原则四。现实中,你仍是你,可是你的能力是在不断成长的。面向对象中由于对象是独立封装的,即对象先天决定它有哪些能力。可是面向接口中,能力是能够后期扩展的。
好比原来会修电脑的人只能是小刚,后面小明本身也会修电脑了,那么,它甚至能够本身修电脑。而这个修改,并不须要在源码上进行。由于源码已经很好体现了这些现实逻辑,无论小明本身会不会修,原来的设计是不变的。一个对象能够拥有多个能力,被多方使用,能力能够是先天的,也能够是后期扩展的。对于上例代码,如今能够经过以下代码为小明增长修电脑的能力。
复制代码
extend 小明: 会修电脑的人 {
public void 修电脑(电脑 a){
// 修电脑的逻辑
}
}
复制代码
讲到如今彷佛都没有提到接口两个字。接口其实就是一份证书:用于约定一个生物具备哪些能力。上例中的 “会修电脑的人” 就是一种能力的约定-----即它是一个接口。理论上任何能力均可以用接口来描述,但这显然不现实(生活中不可能为任何能力都提供一份证书:会烧饭证书?会写字证书?)所以,咱们使用同一类生物还借代:好比小刚是会修电脑的人,那么用小刚来借代全部会修电脑的人(就像平时说的邻居家的孩子来借代拥有各类能力的孩子)。
面向接口中,咱们假设一切生物在起初是没有任何能力的,全部能力都是后期根据须要再提供的。可是这些能力和这个生物自己的资产是没有关系的。 html