1. 程式人生 > >【Java程式設計思想】9.介面

【Java程式設計思想】9.介面

介面和內部類為我們提供了一種將介面與實現分離的更加結構化的方法。


9.1 抽象類和抽象方法

Java 提供抽象方法機制,這種方法時不完整的,僅有宣告,沒有方法體。
包含抽象方法的類叫做抽象類。如果一個類包含一個或多個抽象方法,那麼該類必須被限定為是抽象的(否則編譯器報錯)。

一個抽象類不完整的時候,試圖建立物件時,編譯器會出錯(為抽象類建立物件是不安全的),編譯器會保證抽象類的純粹性。
從一個抽象類繼承後,如果想建立該匯出類的物件,那麼必須為基類中所有抽象方法提供方法實現。不這麼做,匯出類便也是抽象類,編譯器會強制使用 abstract 關鍵字限定匯出類。

抽象類和抽象方法不僅讓類的抽象性明確起來,而且抽象類在重構的時候,可以方便的將公共方法沿著繼承層級結構向上移動。


9.2 介面

  • abstract 關鍵字允許在類中建立一個或多個沒有任何定義的方法-->提供了介面部分,但是沒有提供任何相應的具體實現(其實抽象類中也可以選擇實現個別方法)。
  • interface 關鍵字比抽象類跟進了一步,其會產生一個完全抽象的類,沒有提供任何實現,只允許定義方法名、引數列表和返回型別,沒有任何方法體。

一個介面代表著“所有實現了該特定介面的類看起來都這個樣”。所以介面被用來建立類與類之間的協議
介面中的方法隱式的被視為 public 的。
介面可包含域,這些域隱式的是 static 和 final 的。
當使用一個類去實現介面時,使用 implements

關鍵字,表示”interface 只是其外貌,現在我要宣告它是如何工作的


9.3 完全解耦

建立一個能夠根據所傳遞的引數物件的不同而具有不同行為的方法,被稱為策略設計模式。這類方法包含所要執行的演算法中固定不變的部分,而”策略“包含變化的部分。

此章節還講解了介面卡設計模式,關於設計模式可以檢視歸檔資料中的 Java 設計模式。


9.4 Java 中的多重繼承

Java 中可以組合多個介面,被稱為多重繼承
在匯出類中,不強制要求必須有偶一個是抽象的或者是“具體的”基類。繼承類只能一次,但是實現介面可以有若干個。實現的多個介面,都可以向上轉型為每個介面(因為每個介面都是一個獨立型別)。

使用介面的核心原因:

  • 能夠向上轉型為多個基類型別(以及由此而帶來的靈活性)。
  • 防止客戶端程式設計師建立該類的物件,並確保這僅僅是建立一個介面
    • 建立不帶任何方法定義和成員變數的基類,就應該選擇介面,而不是抽象類。

9.5 通過繼承來拓展介面

一個介面可以繼承其他多個介面。來實現方法的拓展。

一般情況下只可以將 extends 用於單一類的繼承,但是也用多個基類介面。

在不同介面中,最好不要使用相同名稱的方法,會造成可讀性混亂,以及覆蓋、實現和過載混雜在一起的結果。


9.6 適配介面

關於策略設計模式:需要編寫一個執行某些操作的方法,該方法接收一個指定的介面。然後宣告:可以使用任何需要的物件來呼叫方法,只要這個物件遵循指定的介面。

到這裡說句題外話,雖然內容上介面部分比繼承少了許多,但是介面的思想以及在設計模式中的應用,是繼承思想的發揚光大,後續在研究設計模式的時候要再次加深理解。


9.7 介面中的域

放入介面中的任何域都是 static 和 final 的-->介面可以很方便的管理和建立常量組。

  • 介面中定義的域不能使“空 final”的,但是可以被非常量表達式(例如帶有運算子的值)初始化。
  • 在介面中的域首次被訪問時,就可以在類第一次被載入的時候初始化。
  • 這些域的值被儲存在該介面的靜態儲存區中

9.8 巢狀介面

介面可以巢狀在類或者而其它介面中。

類中巢狀的介面,可以被實現為 private,這樣實現可以強制該介面中的方法定義不要新增任何型別資訊(換句話講就是,不允許向上轉型)。
介面中巢狀的介面,作用域介面的各種規則,特別是所有的介面元素都必須是 public 的。
實現某個介面的時候,並不需要實現巢狀在其內部的任何介面,而且 private 介面不能再定義它之外的類被實現。


9.9 介面與工廠

工廠方法設計模式:(純介面實現的工廠方法)

interface Service {
    void method1();
    void method2();
}

interface ServiceFactory {
    Service getService();
}

class Implementation1 implements Service {
    Implementation1() {} // Package access
    @Override
    public void method1() {print("Implementation1 method1");}
    @Override
    public void method2() {print("Implementation1 method2");}
}

class Implementation1Factory implements ServiceFactory {
    @Override
    public Service getService() {
        return new Implementation1();
    }
}

class Implementation2 implements Service {
    Implementation2() {} // Package access
    @Override
    public void method1() {print("Implementation2 method1");}
    @Override
    public void method2() {print("Implementation2 method2");}
}

class Implementation2Factory implements ServiceFactory {
    @Override
    public Service getService() {
        return new Implementation2();
    }
}

public class Factories {
    public static void serviceConsumer(ServiceFactory fact) {
        Service s = fact.getService();
        s.method1();
        s.method2();
    }
    public static void main(String[] args) {
        serviceConsumer(new Implementation1Factory());
        // Implementations are completely interchangeable:
        serviceConsumer(new Implementation2Factory());
    }
} 

輸出:

Implementation1 method1
Implementation1 method2
Implementation2 method1
Implementation2 method2