如何理解接口-Java系列

目錄結構

  • 前言
  • 什麼是接口?
  • 如何聲明接口?
  • 接口的做用?
  • 何時能夠考慮使用接口?
  • 何時能夠不考慮使用接口?
  • 在線接口文檔化平臺
  • 總結

前言

今天有個同事問我,如何理解接口,恰好中午下班要去吃飯,邊走邊說,可是都沒有說到重點,因此想經過這篇文章來分享一下本身對接口的理解,閱讀須要2分鐘。html

什麼是接口?

對象經過它們公開的方法來定義它們與外界的交互行爲,而方法就造成了與外界交互的接口。例如電視機的開關按鈕就是你與塑料外殼另外一側的電線之間的接口,你只要按下電源開關這個按鈕,就能夠控制電視機開機和關機,而你不須要關注電視機開機和關機的細節,接口就是讓你知道它在作什麼,而無需知道它們怎麼作;接口更深層的理解是:使定義(規範和約束)和實現(具體的代碼邏輯)分離,它是溝通(交互)的中介物(具體實現)的抽象化java

如何聲明接口?

public inteface TV {

    // 開機
    public void open();
    
    // 關機
    public void close();
    
    // 選擇頻道
    public void selectChannel(Integer channel);
    
    // 設置聲音大小
    public void setVolume(Integer vlume);
    
    ...
}
複製代碼

上面聲明瞭電視機的接口(編程語言層面的接口),暴露4個方法(與外界交互的接口),經過閱讀這些方法,你腦海裏大體能夠對這個電視機建模,而且知道這個電視機能夠作些什麼,這樣你們就都達成了一個共識,電視機都會具備哪些功能了;而具體要怎麼實現電視機的那些功能(開機、關機、選頻道、設置聲音大小)呢?這就交給不一樣的電視機廠商吧。算法

// 小米電視
public inteface MiTV extends TV {
    // 擴展玩遊戲接口
    public void playGame(String gameId);
}

public class MiTVImpl implements MiTV {

    @Overide
    pubilc void open() {
        // TODO 小米對開機的實現
    }
    
    @Overide
    public void close() {
        // TODO 小米對關機的實現
    }
    
    @Overide
    public void selectChannel(Integer channel) {
        // TODO 小米對選擇頻道的實現
    }
    
    @Overide
    public void setVolume() {
        // TODO 小米對聲音大小控制的實現
    }
    
    // 擴展玩遊戲接口
    @Overide
    public void playGame(String gameId) {
        // TODO 對遊戲的實現
    }
}
複製代碼

從上面的代碼中能夠知道,小米電視機不只實現了電視機的基本操做,自身還擴展了玩遊戲的接口,用戶只須要經過選擇小米電視提供的遊戲,就能夠玩遊戲啦。編程

接口的做用?

  1. 接口便是設計:在設計層面,接口能夠避免咱們陷入對細節的過多思考,可讓咱們站在一個更高的視角對系統作更好的評估,好比系統的交互設計是否合理,功能是否缺失,是否具有可行性,是否過於複雜等等。
  2. 接口便是約定:在編碼層面,接口能夠明確的告訴開發人員如何使用(接口的語義,須要什麼做爲輸入,會有什麼輸出),而開發人員只須要根據這些約定去實現具體的功能代碼便可。
  3. 統一類的共同行爲:接口用來統一類的共通行爲,當不一樣的類須要進行信息共享時,是不須要特別去建立類間的關係。舉例來講,一我的(Human)及一隻鸚鵡(Parrot)都會吹口哨(whistle),然而 Human 及 Parrot 不該該爲 Whistler 的子類,最好的作法是令他們爲 Animal 的子類,而他們可使用 Whistler 的接口進行溝通。
// 吹口哨
public inteface Whistler {
    /** * 吹口哨 */
    public void whistle();
}

public class JuniorWhistler implements Whistler {
    public void whistle() {
        System.out.println("入門級口哨聲");
    }
}

public class SeniorWhistler implements Whistler {
    public void whistle() {
        System.out.println("高級口哨聲");
    }
}

// 定義動物接口
public inteface Animal {
    /** * 吹口哨 * * @param whistle * @return */
    public void whistle(Whistler whistle);
}

public class Human implements Animal {
    
    public void whistle(Whistler whistle) {
        whistle.whistle();
    }
    ...
}

public class Parrot implements Animal {

    public void whistle(Whistler whistle) {
        whistle.whistle();
    }
    ...
}

public class Demo {
    public static void main(String[] args) {
        // 人吹口哨
        Human human = new Human();
        human.whistle(new JuniorWhistler());  // 入門級口哨聲
        
        // 鸚鵡口哨
        Human human = new Human();
        human.whistle(new SeniorWhistler()); // 高級口哨聲
    }
}
複製代碼
  1. 使用時無需知道實現類:當接口有實現類時,在使用它的時候無需知道它的實現類是什麼(感興趣的能夠了解一下多態依賴注入)。例如,一個事物由於口哨的噪音影響到其餘人,對於其餘人而言,就不須要知道噪音來源是來自人仍是鸚鵡,由於他們能夠肯定,一個會吹口哨的事物正在吹口哨。舉一個更實際的例子,排序算法可能會期待對象的類型是能夠被比較的,因而它只須要知道對象的類型能夠被以某種方式進行排序便可,這與對象的類型無關。whistler.whistle() 將會調用對象的實現方法 whistle,而不須要知道對象是以哪一個類來實現 Whistler。
public inteface Whistler {
    public void whistle();
}

public class Human implements Animal {
    
    public void whistle(Whistler whistle) {
        whistle.whistle();
    }
    ...
}
複製代碼

Human 類中的 whistle() 方法的實現 whistle.whistle() 不須要知道口哨具體的實現類是哪一個,而 whistle(Whistler whistle)方法 只關注入參是 Whistler 類型就行。 至於 Java 如何實現動態綁定到具體的實現類上的方法,這個以後另開一篇文章來寫。oracle

何時能夠考慮使用接口?

這雖然很難去定義(即便不少人一直使用面向接口編程),但我的仍是根據自身的開發經驗淺談一下,若是說的不對,歡迎你們指教。框架

  1. 當項目沒有良好的開發規範、API文檔還沒出、項目緊,當項目組有很多新人多時,須要使用接口,而這個接口的定義應該由有經驗、對業務和項目較爲了解的人去定義,這樣子就能夠嚴格約定好接口的輸入輸出、接口命名、參數命名,而不會被亂來,而新人只須要寫對應的實現就能夠,這樣子在重構的時候,不會致使因爲各類奇奇怪怪的問題而去改接口,一旦改了接口,出問題的可能性會更大(這個坑踩過,痛過,特別是沒有單元測試來作迴歸測試的時候)。
  2. 當須要使用到策略模式的時候,應該基於接口來實現,好比不一樣國家的貨幣換算等。
  3. 當框架功能對於系統基於接口設計的擴展很是友好時,應該使用接口,好比依賴注入,這個時候,接口可使系統更具擴展性,更符合Open Close原則
  4. 基於SOA理念,暴露出來的服務必須是接口——阿里的Java開發規範手冊裏面就有嚴格說到這點。

何時能夠不考慮使用接口?

  1. 小項目,參與的人數較少時,時間緊,能夠考慮不須要使用到接口,由於接口自己就很少,無需增長各類文檔化的工做量。

在線接口文檔化平臺

推薦的一些在線API管理平臺 Swagger Editoreolinker編程語言

  • swagger 偏向開發人員,須要掌握編寫swagger文檔的一些語法,上手稍慢,但界面好看,功能也強大。
  • eolinker 所有都是圖形化,上手快,功可以用。

總結

本文經過一些例子和我的的開發經驗,從接口的定義、接口的聲明、再到接口的適用場景,來與讀者分享本人對接口的理解,但願能夠給讀者一些收穫,若是發現本人有理解不對的地方,或者有須要補充的地方,歡迎評論交流。ide

相關文章
相關標籤/搜索