java介面卡模式
1、概述
什麼是介面卡模式?
介面卡模式是一種結構型設計模式。介面卡模式就是:把一個類的介面變換成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠在一起工作。
用電器來打個比喻:有一個電器的插頭是三腳的,而現有的插座是兩孔的,要使插頭插上插座,我們需要一個插頭轉換器,這個轉換器即是介面卡。
介面卡模式涉及3個角色:
- 源(Adaptee):需要被適配的物件或型別,相當於插頭。
- 介面卡(Adapter):連線目標和源的中間物件,相當於插頭轉換器。
- 目標(Target):期待得到的目標,相當於插座。
2、介面卡模式UML圖
圖片來自網路
通過上面UML圖可以知道,客戶端期待的介面或者物件通過介面卡的轉換得到了滿足,Adapter通過內部包裝Adaptee物件把源物件轉換成客戶端期待的物件。
3、介面卡模式分類
介面卡模式包括3種形式:
- 類介面卡模式:類介面卡使用的是繼承的方式,一般來說無法對其子類進行適配
- 物件介面卡模式:物件介面卡使用的是組合的方式,子孫類都可以被適配。另外,物件介面卡對於增加一些新行為非常方便,而且新增加的行為同時適用於所有的源。
- 介面介面卡模式(又稱預設介面卡模式):介面介面卡模式(預設適配模式)基本思想是,為一個介面提供預設實現,這樣子類可以從這個預設實現進行擴充套件,而不必從原有介面進行擴充套件。
可以說對象介面卡模式是另外6種結構型設計模式的起源(圖片源自網路)。
4、三種介面卡模式詳解
介面卡模式的三種實現方式及程式碼例項詳解,用電器來打個比喻:有一個電器的插頭是兩腳的,而現有的插座是三孔的,要使插頭插上插座,我們需要一個插頭轉換器,這個轉換器即是介面卡。
圖片源自網路
4.1、類介面卡模式
類介面卡使用的是繼承的方式,一般來說無法對其子類進行適配,請看程式碼例項
1.首先我們有一個要被適配的類
/** * 源(相當於兩腳插頭,也就是被適配的類) * @author ningbeibei */ public class Adaptee { public void adapteeMethod() { System.out.println("兩腳插頭,被適配的類...."); } }
2.定義一個目標介面
/** * 目標(客戶所期待的類,可以是一個介面抽象類具體的類) * 相當於三孔插板 * @author ningbeibei */ public interface Target { void targetMethod(); }
3.定義介面卡類
定義介面卡類通過繼承 Adaptee 和實現 Target 介面關聯起來,
/** * 類介面卡模式(相當於轉換器) * 通過Adapter類把Adaptee類與Target介面銜接起來 * @author ningbeibei */ public class Adapter extends Adaptee implements Target { @Override public void targetMethod() { //操作處理 adapteeMethod(); //操作處理 } }
4.測試程式碼
/** * 介面卡模式測試類 * @author ningbeibei */ public class test { public static void main(String[] args) { //類介面卡模式 Adapter adapter = new Adapter(); adapter.targetMethod(); } }
5.執行結果
4.2、物件介面卡模式
物件介面卡使用的是組合的方式,它把源類作為屬性放入介面卡類中,請看程式碼例項
1.定義被適配的類
/** * 源(相當於兩腳插頭,也就是被適配的類) * @author ningbeibei */ public class Adaptee { public void adapteeMethod() { System.out.println("兩腳插頭,被適配的類...."); } }
2.定義目標介面
/** * 目標(客戶所期待的類,可以是一個介面抽象類具體的類) * 相當於三孔插板 * @author ningbeibei */ public interface Target { void targetMethod(); }
3.定義介面卡類(類似於轉換器)
注意:通過持有Adaptee屬性建立與Target介面聯絡
/** * 物件介面卡模式(相當於轉換器) * 通過持有Adaptee屬性建立與Target介面聯絡 * @author ningbeibei */ public class Adapter implements Target { //新增屬性 private Adaptee adaptee; public Adapter (Adaptee adaptee) { this.adaptee = adaptee; } @Override public void targetMethod() { //操作處理 adaptee.adapteeMethod(); //操作處理 } }
4.測試類
/** * 介面卡模式測試類 * @author ningbeibei */ public class test { public static void main(String[] args) { //物件介面卡模式 Adapter adapter = new Adapter(new Adaptee()); adapter.targetMethod(); } }
5.結果輸出
4.3、介面介面卡模式(預設適配模式)
介面介面卡模式又稱預設模式,這種模式通過抽象類對介面進行實現,在抽象類種對介面進行預設實現。請看下面程式碼示例
1.定義頂層介面
/** * 定義頂層介面 * @author ningbeibei */ public interface Target { void targetMethod(); void targetMethod1(); void targetMethod2(); }
2.定義抽象類 AbstrctAdapter 並實現 Target 介面
/** * 介面介面卡模式 * 定義抽象類並實現Target介面 * @author ningbeibei */ public abstract class AbstrctAdapter implements Target { //預設實現方法 public void targetMethod() { System.out.println("預設實現"); }; //需要子類必須實現的方法 public abstract void targetMethod1(); //需要子類重寫這個方法 public void targetMethod2() { System.out.println("預設實現2"); }; }
3.定義Adapter類並繼承AbstrctAdapte抽象類
通過介面和抽象類的結合,避免了在實現介面的子類中出現大量的“無意義”實現,這個“無意義”實現,被緩衝到了抽象類中,完美展現了程式碼複用(可以把抽象類理解成介面和實現類之間的緩衝)
/** * 通過繼承AbstrctAdapter抽象類 * 實現它的抽象方法和重寫方法 * 這種方式是通過抽象類緩衝介面中那些我們不想實現的空方法 * @author ningbeibei */ public class Adapter extends AbstrctAdapter { @Override public void targetMethod1() { System.out.println("子類必須實現"); } public void targetMethod2() { System.out.println("重寫實現2"); }; }
4.測試類
/** * 預設模式 * @author ningbeibei */ public class test { public static void main(String[] args) { Adapter adapter = new Adapter(); adapter.targetMethod(); adapter.targetMethod1(); adapter.targetMethod2(); } }
5.結果輸出
通過上面結果輸出我們可以得道以下幾點:
- 提供方法預設實現
- 決定子類必須要實現方法
- 子類可以決定是否重新父類方法
- 通過介面和抽象類的結合,避免了在實現介面的子類中出現大量的“無意義”實現,這個“無意義”實現,被緩衝到了抽象類中
5、介面卡模式的優缺點
5.1、優點
更好的複用性:系統需要使用現有的類,而此類的介面不符合系統的需要。那麼通過介面卡模式就可以讓這些功能得到更好的複用。
更好的擴充套件性:在實現介面卡功能的時候,可以擴充套件自己源的行為(增加方法),從而自然地擴充套件系統的功能。
5.2、缺點
會導致系統紊亂:濫用介面卡,會讓系統變得非常零亂。例如,明明看到呼叫的是A介面,其實內部被適配成了B介面的實現,一個系統如果太多出現這種情況,無異於一場災難。因此如果不是很有必要,可以不使用介面卡,而是直接對系統進行重構。