設計模式六大原則(4):接口隔離原則

承接上文,我們繼續設計模式六大原則的心法要訣四:接口隔離原則。

什麼是接口隔離原則?其要訣是啥?

定義:客戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。
要訣:接口最小化原則,強調的是一個接口擁有的行爲應該儘可能的小。

那麼具體的場景和招式呢?

問題由來:類A通過接口I依賴類B,類C通過接口I依賴類D,如果接口I對於類A和類B來說不是最小接口,則類B和類D必須去實現他們不需要的方法。
解決方案:將臃腫的接口I拆分爲獨立的幾個接口,類A和類C分別與他們需要的接口建立依賴關係。也就是採用接口隔離原則。
舉個栗子:現在我們通過A類這個耕地的拖拉機通過標準的接口I,依賴與實現類B,在B類中有耕地的耙犁和動力能源柴油,可是我們現在要用這個拖拉機來實現C類拉貨的功能,那麼我們就在I中接入車斗,在D類中實現車斗的功能,但是在實現時候也必須實現接口I中關於A類所需的功能,這不是多餘麼,所以這個時候我們就將這個接口細化爲I1專管耕地需要的零件,I2專管運貨需要的零件,I3我們就是動力發動機零件了,這樣一來這個拖拉機就是萬能拖拉機,不受臃腫的藉口而變靈活了,老司機也開着清爽。

看完了心法口訣,我們來實戰:
招式一:舉個大栗子

/*測試模塊*/
public class Function03 {
    public static void main(String[] arg0){
        Tractor1 tractor1 = new Tractor1();
        tractor1.depend1(new TractorForPlogh());
        tractor1.depend2(new TractorForPlogh());

        Tractor2 tractor2 = new Tractor2();
        tractor2.depend1(new TractorForHopper());
        tractor2.depend2(new TractorForHopper());
    }
}

/*拖拉機的標準接口*/
interface ITractor1{
    public void oil();
    public void plough();
    public void hopper();
}
/*拖拉機實現類--實現耕地*/
class Tractor1{
    public void depend1(ITractor1 iTractor1){
        iTractor1.oil();
    }
    public void depend2(ITractor1 iTractor1){
        iTractor1.plough();
    }
}
/*拖拉機耕地所需的元件*/
class TractorForPlogh implements ITractor1{

    @Override
    public void oil() {
        System.out.println("拖拉機的動力來源:柴油。。。");
    }

    @Override
    public void plough() {
        System.out.println("拖拉機的耕地的工具:耙犁。。。");
    }
    //在拖拉機耕地的時候是不需要車斗的,所以在這裏只是一個空的實現方法
    @Override
    public void hopper() {

    }
}
/*拖拉機實現類--實現貨運*/
class Tractor2{
    public void depend1(ITractor1 iTractor1){
        iTractor1.oil();
    }
    public void depend2(ITractor1 iTractor1){
        iTractor1.hopper();
    }
}

class TractorForHopper implements ITractor1{

    @Override
    public void oil() {
        System.out.println("拖拉機的動力來源:柴油。。。");
    }
    //拖拉機在貨運的時候是不需要耙犁的,所以這裏是空的實現
    @Override
    public void plough() {

    }

    @Override
    public void hopper() {
        System.out.println("拖拉機貨運需要的容器:車斗。。。");
    }
}

運行結果:

拖拉機的動力來源:柴油。。。
拖拉機的耕地的工具:耙犁。。。
拖拉機的動力來源:柴油。。。
拖拉機貨運需要的容器:車斗。。。
我們可以看到,如果接口過於臃腫,只要接口中出現的方法,不管對依賴於它的類有沒有用處,實現類中都必須去實現這些方法,這顯然不是好的設計。如果將這個設計修改爲符合接口隔離原則,就必須對接口I進行拆分。

招式二:拆分重接

/*拖拉機的標準接口--柴油*/
interface ITractor1{
    public void oil();
}
/*拖拉機的標準接口--耙犁*/
interface ITractor2{
    public void plough();
}
/*拖拉機的標準接口--車斗*/
interface ITractor3{
    public void hopper();
}
/*拖拉機實現類--實現耕地*/
class Tractor1{
    public void depend1(ITractor1 iTractor1){
        iTractor1.oil();
    }
    public void depend2(ITractor2 iTractor2){
        iTractor2.plough();
    }
}
/*拖拉機耕地所需的元件*/
class TractorForPlogh implements ITractor1,ITractor2{

    @Override
    public void oil() {
        System.out.println("拖拉機的動力來源:柴油。。。");
    }

    @Override
    public void plough() {
        System.out.println("拖拉機的耕地的工具:耙犁。。。");
    }
/*    //在拖拉機耕地的時候是不需要車斗的,所以在這裏只是一個空的實現方法
    @Override
    public void hopper() {

    }*/
}
/*拖拉機實現類--實現貨運*/
class Tractor2{
    public void depend1(ITractor1 iTractor1){
        iTractor1.oil();
    }
    public void depend2(ITractor3 iTractor3){
        iTractor3.hopper();
    }
}

class TractorForHopper implements ITractor1,ITractor3{

    @Override
    public void oil() {
        System.out.println("拖拉機的動力來源:柴油。。。");
    }
    /*//拖拉機在貨運的時候是不需要耙犁的,所以這裏是空的實現
    @Override
    public void plough() {

    }*/

    @Override
    public void hopper() {
        System.out.println("拖拉機貨運需要的容器:車斗。。。");
    }
}
我們可以看到,將原來龐大臃腫的接口拆分之後,程序的可維護性和和擴展性變的很顯著,所以接口隔離原則的含義是:建立單一接口,不要建立龐大臃腫的接口,儘量細化接口,接口中的方法儘量少。也就是說,我們要爲各個類建立專用的接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用。本文例子中,將一個龐大的接口變更爲3個專用的接口所採用的就是接口隔離原則。在程序設計中,依賴幾個專用的接口要比依賴一個綜合的接口更靈活。接口是設計時對外部設定的“契約”,通過分散定義多個接口,可以預防外來變更的擴散,提高系統的靈活性和可維護性。

指得注意的是說到這裏,很多人會覺的接口隔離原則跟之前的單一職責原則很相似,其實不然。其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。其二,單一職責原則主要是約束類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口接口,主要針對抽象,針對程序整體框架的構建。


總結:

採用接口隔離原則對接口進行約束時,要注意以下幾點:
接口儘量小,但是要有限度。對接口進行細化可以提高程序設計靈活性是不掙的事實,但是如果過小,則會造成接口數量過多,使設計複雜化。所以一定要適度。
爲依賴接口的類定製服務,只暴露給調用的類它需要的方法,它不需要的方法則隱藏起來。只有專注地爲一個模塊提供定製服務,才能建立最小的依賴關係。
提高內聚,減少對外交互。使接口用最少的方法去完成最多的事情。

運用接口隔離原則,一定要適度,接口設計的過大或過小都不好。設計接口的時候,只有多花些時間去思考和籌劃,才能準確地實踐這一原則。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章