適配器模式,顧名思義,就是把本來不兼容的接口,經過適配,使之兼容。ide
舉個生活中簡單的例子,之前的手機內存卡能夠取出來,可是想和電腦之間傳輸音樂、視頻等資料不能直接傳輸,須要經過USB讀卡器,而後插入USB接口就能夠傳輸了,這個USB讀卡器就至關於適配器。this
你常常使用的手機或電腦充電器,也屬於適配器,它將220V的交流電轉換爲手機可用的直流電。下面,以手機充電器爲例講解適配器模式。設計
適配器模式通常分爲三類:類適配器模式、對象適配器模式、接口適配器模式(缺省適配器模式)code
1、類適配器模式視頻
通常手機充電器輸出的直流電壓爲5V,咱們把交流電220V稱爲源,但願獲得的直流電5V稱爲目標,而充電器即爲適配器。對象
//源,交流電 public class AC { public int outputAC(){ return 220; } } //目標接口,直流電 public interface IDC { public int outputDC(); } //適配器 public class ClsAdapter extends AC implements IDC{ @Override public int outputDC() { return outputAC()/44; //直流電爲交流電的電壓值除以44 } public static void main(String[] args) { ClsAdapter adapter = new ClsAdapter(); System.out.println("交流電電壓:" + adapter.outputAC()); System.out.println("直流電電壓:" + adapter.outputDC()); } } /** 輸出結果爲: 交流電電壓:220 直流電電壓:5 */
能夠看到,類適配器是經過繼承源類,實現目標接口的方式實現適配的。可是,因爲Java單繼承的機制,這就要求目標必須是接口,有必定的侷限性。繼承
2、對象適配器模式接口
對象適配器,不是繼承源類,而是依據關聯關係,持有源類的對象,這也隱藏了源類的方法。在這裏,適配器和源類的關係不是繼承關係,而是組合關係。內存
public class ObjAdapter implements IDC { //持有源類的對象 private AC ac; public ObjAdapter(AC ac){ this.ac = ac; } public int outputAC(){ return ac.outputAC(); } @Override public int outputDC() { return ac.outputAC()/44; } public static void main(String[] args) { ObjAdapter adapter = new ObjAdapter(new AC()); System.out.println("交流電電壓:" + adapter.outputAC()); System.out.println("直流電電壓:" + adapter.outputDC()); } } //輸出結果同上
3、接口適配器模式get
設想,我如今的目標接口有多個方法,能夠輸出5V,12V,20V的電壓。按照正常邏輯,設計一個適配器去實現這個接口,很顯然須要實現全部的方法。可是,實際使用中,其實只須要使用其中一個方法就能夠了,好比我mac電腦直流電壓20V,只須要實現20V的方法就能夠了。
所以,設計一箇中間類去把目標接口的全部方法空實現,而後適配器類再去繼承這個中間類,選擇性重寫我所須要的方法,豈不是更好。代碼以下,
//目標接口,有多個方法 public interface IDCOutput { public int output5V(); public int output12V(); public int output20V(); } //中間類,空實現全部方法,這是一個抽象類 public abstract class DefaultAdapter implements IDCOutput { @Override public int output5V() { return 0; } @Override public int output12V() { return 0; } @Override public int output20V() { return 0; } } //個人mac電源適配器只須要實現20V的方法便可 public class MacAdatper extends DefaultAdapter { private AC ac; public MacAdatper(AC ac){ this.ac = ac; } @Override public int output20V() { return ac.outputAC()/11; } public static void main(String[] args) { MacAdatper adatper = new MacAdatper(new AC()); System.out.println("mac電腦電壓:" + adatper.output20V()); } } //輸出結果: //mac電腦電壓:20
至於爲何中間類使用抽象類,相信你看過我介紹的軟件六大設計原則,就明白了(你不得不知道的軟件設計六大原則)。它須要符合里氏替換原則(儘可能基於抽象類和接口的繼承)。
不太明白接口適配模式的童鞋,建議看一下JDK裏邊提供的一個鍵盤監聽適配器KeyAdapter,它就是一個抽象類,去空實現了KeyListener接口的全部方法。你就會感覺到這種模式的奧妙。
總結:
類適配器模式,繼承源類,實現目標接口。
對象適配器模式,持有源類的對象,把繼承關係改變爲組合關係。
三種模式,各有優缺點,可根據實際狀況選擇使用。