1.介面定義 介面屬於一個特殊的類,這個類裡面只能有抽象方法和全局常量 (該概念在JDK1.8之後被打破,在1.8後介面中還可以定義普通方法和靜態方法,在後續章節會詳講) 1.1 介面具有以下幾個原則 介面通過interface關鍵字來實現定義 一個子類如果要繼承介面的話,則需要通過implemen ...
1.介面定義
介面屬於一個特殊的類,這個類裡面只能有抽象方法和全局常量 (該概念在JDK1.8之後被打破,在1.8後介面中還可以定義普通方法和靜態方法,在後續章節會詳講)
1.1 介面具有以下幾個原則
- 介面通過interface關鍵字來實現定義
- 一個子類如果要繼承介面的話,則需要通過implements關鍵字去實現多個介面(多介面之間通過","隔開),從而實現多繼承.
- 介面的子類如果不是個抽象類,則必須要覆寫介面的所有抽象方法,才能承認該類實現了這個介面
- 介面的子對象可以通過向上轉型進行實例化操作
1.2 接下來來個示例,通過Demo類繼承InA和InB兩個介面
interface InA //介面InA { public static final String ATTR = "Attribute:InA"; public abstract void PrintA(); } interface InB //介面InB { public static final String ATTR = "Attribute:InB"; public abstract void PrintB(); } class Demo implements InA,InB { public void PrintA() { System.out.println(InA.ATTR); //列印介面A的全局常量 } public void PrintB() { System.out.println(InB.ATTR); //列印介面B的全局常量 } } public class Test{ public static void print(InB b) //介面支持向上轉型 { b.PrintB(); } public static void main(String args[]) { Demo d = new Demo(); d.PrintA(); //列印介面A的全局常量 print(d); //等價於d.PrintB(); } }
運行列印:
從上面代碼可以看出,介面實際上只是表示一種操作標準 ,而介面本身其實是沒有操作能力的,需要子類去實現這個操作能力才行.
2.介面的簡化定義
由於介面組成部分是抽象方法和全局常量,所以在方法和常量上寫不寫public結果都一樣,並且方法也可以不用abstract修飾,因為介面里的訪問許可權都是public的,並且方法預設為抽象的,所以InA介面也可以寫為下麵這樣:
interface InA //介面InA { String ATTR = "Attribute:InA"; //不需要添加public static final void PrintA(); //不需要添加public abstract }
3.介面定義註意的地方
3.1 對於子類或者抽象子類,可以同時繼承抽象類以及多個介面,比如:
class Demo extends A implements InA,InB{ // Demo子類繼承於A類,以及介面inA和inB //... ... //實現所有抽象方法 }
3.2 對於一個子介面,以通過extends來繼承多個父介面,比如:
interface InC extends InA,InB{ //InC子介面繼承父介面inA和inB public void funcC(); //定義抽象方法 }
3.3 介面不能繼承於抽象類,因為extends關鍵字用於繼承同一品種的(介面!=抽象類),而 implements用於繼承於介面的(抽象類!=介面),所以無法實現.
4.介面之工廠設計模式Factory
工廠設計模式,就是說建立一個工廠類,對實現了同一介面的子類們進行統一的實例創建方法,用來提供給用戶調用.而用戶無需去瞭解這些對象該如何創建以及如何組織.
4.1工廠設計示例
我們以常用的usb為例,首先需要定義一個USB介面,然後寫同一介面的子類們(比如:鍵盤,滑鼠,印表機).由於這些子類們都是獨立的,所以我們需要在定義一個工廠類UsbFactory,通過一個方法去統一創建他們,如果不寫工廠類的話,假如有100多個USB子類,那豈不是全部創建都要100多個不同的new才行?所以需要一個工廠類負責管理這些對象.
首先定義USB介面和鍵盤,滑鼠子類:
interface USB //USB介面 { public void plugin(); public void out(); } class Keyboard implements USB { public void plugin() { System.out.println("****插上 usb鍵盤****"); } public void out() { System.out.println("****取出 usb鍵盤****"); } } class Mouse implements USB { public void plugin() { System.out.println("****插上 usb滑鼠****"); } public void out() { System.out.println("****取出 usb滑鼠****"); } }
然後定義UsbFactory工廠類:
class UsbFactory { static public USB getInstance(String name) { if("keyboard".equals(name)) //是否為鍵盤 return new Keyboard(); else if("mouse".equals(name)) //是否為鍵盤 return new Mouse(); else return null; } }
最後寫測試代碼:
public class Test{ public static void main(String args[]) { USB usb1 = UsbFactory.getInstance("keyboard"); //獲取鍵盤類 usb1.plugin(); usb1.out(); USB usb2 = UsbFactory.getInstance("mouse"); //獲取滑鼠類 usb2.plugin(); } }
列印如下:
從上面代碼可以看出,通過工廠模式,我們可以更加容易地管理多個相同介面的子類們的操作.
5.代理模式proxy
代理模式,就是說為一個具體對象提供一個代理對象,該代理對象主要是為了封裝具體對象,並且完成與具體對象有關的所有操作.而具體對象則只需要負責核心業務.
5.1 代理設計示例
我們以生活中的Eat吃為例,首先需要定義一個Eat介面,然後寫一個具體類WhatEat(用來指定具體吃什麼),但是在生活中,我們如果吃的不是水果,而是蔬菜,則都要有盤子啊,並且吃之前要先去燒菜盛菜,並且吃完後還要洗碗.而這些操作,我們就不能寫在WhatEat類里,因為WhatEat類只負責核心業務(吃),所以便有了代理對象(完成與具體對象有關的所有操作),接下來便寫一個EatProxy代理節點類來實現這些與WhatEat類操作.
首先定義Eat介面和具體吃的類(WhatEat):
interface Eat { public int TypeVegetable = 0; //蔬菜 public int TypeFruit = 1; //水果 public void eat(int type); } class WhatEat implements Eat { public void eat(int type) { if(type == Eat.TypeVegetable) System.out.println("*** 吃蔬菜 ***"); else System.out.println("*** 吃水果 ***"); } }
然後定義EatProxy代理節點類:
class EatProxy implements Eat { private Eat eatObject; //代理下的具體對象 public EatProxy(Eat eatObject) { this.eatObject = eatObject; } public void eat(int type) //吃東西 { this.eatPrepare(type); this.eatObject.eat(type); this.eatFinish(type); } private void eatPrepare(int type) //吃東西之前的準備工作 { if(type == Eat.TypeVegetable) { System.out.println("正在燒菜... ..."); System.out.println("燒菜完成,正在盛菜"); System.out.println("盛菜完成,準備開吃"); } else { System.out.println("正在洗水果,削皮中..."); System.out.println("削皮完成,準備開吃"); } } private void eatFinish(int type) //吃完東西之後的工作 { if(type == Eat.TypeVegetable) { System.out.println("吃完了,準備洗碗..."); } else { System.out.println("吃完了,準備乾其它事..."); } } }
最後寫測試代碼:
public class Test{ public static void main(String args[]) { EatProxy proxy = new EatProxy(new WhatEat()); proxy.eat(Eat.TypeFruit); //通過代理節點吃水果 //分割線 System.out.println(); System.out.println(); proxy.eat(Eat.TypeVegetable); //通過代理節點吃蔬菜 } }
列印如下所示:
從上面可以看到,我們WhatEat類只需要完成吃(核心業務),可以發現通過代理可以降低不同類之間的依賴性
6.總結
學完介面後,它和抽象類之間的區別如下
區別 |
抽象類 |
介面 |
關鍵字 |
abstract class |
interface |
內部組成 |
支持屬性,常量,構造方法,普通方法,abstract抽象方法,靜態方法等 |
支持全局常量,abstract抽象方法 |
子類繼承 |
class 子類 extends 抽象類{ //... ... } |
class 子類 interface 介面1,介面2,...{ //... ... } |
自身繼承 |
抽象類可以繼承於多個介面,或者抽象類. |
介面可以繼承多個介面,但不能繼承抽象類. |
繼承限制 |
單繼承,一個子類只能繼承一個抽象類 |
多繼承,一個子類可以繼承多個介面 |
未完待續。