接口隔離原則的定義
那么什么是接口?接口分為兩類:
- 實例接口(Object Interface)
在java中聲明一個類,類也是一種接口。 - 類接口(Class Interface)
java中經(jīng)常使用Interface來定義。
接口隔離原則有兩種定義:
第一種定義: Clients should not be forced to depend upon interfaces that they don't use. 客戶端不應(yīng)該依賴它不需用的接口。
第二種定義:The dependency of one class to another one should depend on the smallest possible interface。類間的依賴關(guān)系應(yīng)該建立在最小的接口上。
一個新事物的定義一般都是比較難理解的,晦澀難懂是正常的,否則那會讓人家覺的你沒有水平,這 也是一些國際廠商在國內(nèi)忽悠的基礎(chǔ),不整些名詞怎么能讓你崇拜我呢?我們把這個定義剖析一下,先說 第一種定義客戶端不應(yīng)該依賴它不需要接口,那依賴什么?依賴它需要的接口,客戶端需要什么接口就提 供什么借口,把不需要的接口剔除掉,那就需要對接口進行細(xì)化,保證其純潔性;再看第二個定義,類間 的依賴關(guān)系應(yīng)該建立在最小的接口上,它要求是最小的接口,也是要求接口細(xì)化,接口純潔,與第一個定 義如出一轍,只是一個事物的兩種不同描述。
我們可以把這兩個定義概括為一句話:建立單一接口,不要建立臃腫龐大的接口。再通俗的一點講: 接口盡量細(xì)化,同時接口中的方法盡量的少。看到這里大家有可能要疑惑了,這與單一職責(zé)原則不是相同 的嗎?錯,接口隔離原則與單一職責(zé)的定義的規(guī)則是不相同的,單一職責(zé)要求的是類和接口職責(zé)單一,注 重的是職責(zé),沒有要求接口的方法減少,例如一個職責(zé)可能包含 10 個方法,這 10 個方法都放在一個接口 中,并且提供給多個模塊訪問,各個模塊按照規(guī)定的權(quán)限來訪問,在系統(tǒng)外通過文檔約束不使用的方法不 要訪問,按照單一職責(zé)原則是允許的,按照接口隔離原則是不允許的,因為它要求“盡量使用多個專門的 接口”,專門的接口指什么?就是指提供給多個模塊的接口,提供給幾個模塊就應(yīng)該有幾個接口,而不是建 立一個龐大的臃腫的接口,所有的模塊可以來訪問。
類圖
未遵循接口隔離原則的設(shè)計:

遵循接口隔離原則的設(shè)計:

舉例說明
我們來舉個例子來說明接口隔離原則到底對我們提出了什么要求?,F(xiàn)在男生對小姑娘的稱呼使用頻率 最高的應(yīng)該是“美女”了吧,我們今天來定義一下什么是美女:首先要面貌好看,其次是身材要窈窕,然 后要有氣質(zhì),當(dāng)然了,這三者各人的排列順序不一樣,總之要成為一名美女就必須具備:面貌、身材和氣質(zhì),我們用類圖類體現(xiàn)一下星探(當(dāng)然,你也可以把你自己想想成星探)找美女的過程,看類圖:

定義了一個 IPettyGirl 接口,聲明所有的美女都應(yīng)該有 goodLooking、niceFigure 和 greatTemperament,然后又定義了一個抽象類 AbstractSearcher,其作用就是搜索美女然后展示信息,只 要美女都是按照這個規(guī)范定義,Searcher(星探)就輕松的多了,我們先來看美女的定義:
public interface IPettyGirl {
//要有姣好的面孔
public void goodLooking();
//要有好身材
public void niceFigure();
//要有氣質(zhì)
public void greatTemperament();
}
美女就是這樣的一個定義,各位色狼別把口水流到了鍵盤上,然后我們看美女的實現(xiàn)類:
public class PettyGirl implements IPettyGirl {
private String name;
//美女都有名字
public PettyGirl(String _name){
this. name=_name;
}
//臉蛋漂亮
public void goodLooking() {
System. out.println(this. name + "---臉蛋很漂亮!");
}
//氣質(zhì)要好
public void greatTemperament() {
System. out.println(this. name + "---氣質(zhì)非常好!");
}
//身材要好
public void niceFigure() {
System. out.println(this. name + "---身材非常棒!");
}
}
然后我們來看 AbstractSearcher 類,這個類一般就是指星探這個行業(yè)了,源代碼如下:
public abstract class AbstractSearcher {
protected IPettyGirl pettyGirl;
public AbstractSearcher(IPettyGirl _pettyGirl){
this.pettyGirl = _pettyGirl;
}
//搜索美女,列出美女信息
public abstract void show();
}
場景中的兩個角色美女和星探都已經(jīng)完成了,我們再來寫個場景類,展示一下我們的這個過程:
public class Client {
//搜索并展示美女信息
public static void main(String[] args) {
//定義一個美女
IPettyGirl yanYan = new PettyGirl(" 嫣嫣");
AbstractSearcher searcher = new Searcher(yanYan);
searcher.show();
}
}
星探查找到美女,打印出美女的信息,源碼如下:
public class Searcher extends AbstractSearcher{
public Searcher(IPettyGirl _pettyGirl){
super(_pettyGirl);
}
//展示美女的信息
public void show(){
System. out.println("--------美女的信息如下: ---------------");
//展示面容
super. pettyGirl.goodLooking();
//展示身材
super. pettyGirl.niceFigure();
//展示氣質(zhì)
super. pettyGirl.greatTemperament();
}
}
運行結(jié)果如下:
--------美女的信息如下: ---------------
嫣嫣---臉蛋很漂亮!
嫣嫣---身材非常棒!
嫣嫣---氣質(zhì)非常好!
采用接口隔離原則:重新修改一下類圖:

把原 IPettyGirl 接口拆分為兩個接口,一種是外形美的美女 IGoodBodyGirl,這類美女的特點就是臉 蛋和身材極棒,超一流,但是沒有審美素質(zhì),比如隨地吐痰,出口就是 KAO,CAO 之類的,文化程度比較低; 另外一種是氣質(zhì)美的美女 IGreatTemperamentGirl,談吐和修養(yǎng)都非常高。我們從一個比較臃腫的接口拆分 成了兩個專門的接口,靈活性提高了,可維護性也增加了,不管以后是要外形美的美女還是氣質(zhì)美的美女 都可以輕松的通過 PettyGirl 定義。我們先看兩種類型的美女接口:
public interface IGoodBodyGirl {
//要有姣好的面孔
public void goodLooking();
//要有好身材
public void niceFigure();
}
public interface IGreatTemperamentGirl {
//要有氣質(zhì)
public void greatTemperament();
}
實現(xiàn)類沒有改變,只是實現(xiàn)類兩個接口,源碼如下:
public class PettyGirl implements IGoodBodyGirl,IGreatTemperamentGirl {
private String name;
//美女都有名字
public PettyGirl(String _name){
this. name=_name;
}
//臉蛋漂亮
public void goodLooking() {
System. out.println(this. name + "---臉蛋很漂亮!");
}
//氣質(zhì)要好
public void greatTemperament() {
System. out.println(this. name + "---氣質(zhì)非常好!");
}
//身材要好
public void niceFigure() {
System. out.println(this. name + "---身材非常棒!");
}
}
通過這樣的改造以后,不管以后是要氣質(zhì)美女還是要外形美女,都可以保持接口的穩(wěn)定。當(dāng)然你可能 要說了,以后可能審美觀點再發(fā)生改變,只有臉蛋好看就是美女,那這個 IGoodBody 接口還是要修改的呀, 確實是,但是設(shè)計時有限度的,不能無限的考慮未來的變更情況,否則就會陷入設(shè)計的泥潭中而不能自拔。 以上把一個臃腫的接口變更為兩個獨立的接口依賴的原則就是接口隔離原則,讓 AbstractSearcher 依 賴兩個專用的接口比依賴一個綜合的接口要靈活。接口是我們設(shè)計時對外提供的契約,通過分散定義多個 接口,可以預(yù)防未來變更的擴散,提高系統(tǒng)的靈活性和可維護性。
總結(jié)
接口隔離原則的含義是:建立單一接口,不要建立龐大臃腫的接口,盡量細(xì)化接口,接口中的方法盡量少。也就是說,我們要為各個類建立專用的接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調(diào)用。
在程序設(shè)計中,依賴幾個專用的接口要比依賴一個綜合的接口更靈活。接口是設(shè)計時對外部設(shè)定的“契約”,通過分散定義多個接口,可以預(yù)防外來變更的擴散,提高系統(tǒng)的靈活性和可維護性。
說到這里,很多人會覺的接口隔離原則跟之前的單一職責(zé)原則很相似,其實不然。
其一,單一職責(zé)原則注重的是職責(zé);而接口隔離原則注重對接口依賴的隔離。
其二,單一職責(zé)原則主要是約束類,其次才是接口和方法,它針對的是程序中的實現(xiàn)和細(xì)節(jié);而接口隔離原則主要約束接口接口,主要針對抽象,針對程序整體框架的構(gòu)建。
最佳實踐
采用接口隔離原則對接口進行約束時,要注意以下幾點:
- 接口盡量小,但是要有限度。對接口進行細(xì)化可以提高程序設(shè)計靈活性是不掙的事實,但是如果過小,則會造成接口數(shù)量過多,使設(shè)計復(fù)雜化。所以一定要適度。
- 為依賴接口的類定制服務(wù),只暴露給調(diào)用的類它需要的方法,它不需要的方法則隱藏起來。只有專注地為一個模塊提供定制服務(wù),才能建立最小的依賴關(guān)系。
- 提高內(nèi)聚,減少對外交互。使接口用最少的方法去完成最多的事情。
- 運用接口隔離原則,一定要適度,接口設(shè)計的過大或過小都不好。設(shè)計接口的時候,只有多花些時間去思考和籌劃,才能準(zhǔn)確地實踐這一原則。