10.JAVA-介面、工廠模式、代理模式、詳解
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 Demoimplements 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 Aimplements 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 Keyboardimplements USB { public void plugin() { System.out.println("****插上 usb鍵盤****"); } public void out() { System.out.println("****取出 usb鍵盤****"); } } class Mouseimplements 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[]) { EatProxyproxy = new EatProxy(new WhatEat()); proxy.eat(Eat.TypeFruit);//通過代理節點吃水果 //分割線 System.out.println(); System.out.println(); proxy.eat(Eat.TypeVegetable);//通過代理節點吃蔬菜 } }
列印如下所示:
從上面可以看到,我們WhatEat類只需要完成 吃(核心業務) ,可以發現 通過代理 可以 降低不同類之間的依賴性
未完待續。