定義
適配器模式用于解決接口間的兼容問題。
當我們需要使用某個類提供的接口,但是這個接口與現在的系統需求不符,由于該接口是由第三方提供的,或者是已經在生產上跑了很久的存量類,我們不想通過改變這個類來滿足現在系統的需求,那么這時候就可以考慮通過將目標類封裝成一個滿足系統需求的新類,因此適配器(Adapter)也稱為包裝器(Wrapper)。
結構
適配器模式包含如下角色:
- Target:目標抽象類,客戶類期望的接口。
- Adapter:適配器類,適配器模式的核心,實現目標抽象類和適配者類的轉換。
- Adaptee:適配者類,與目前需求不兼容的類,即需要被包裝的類。
- Client:客戶類,調用在目標抽象類中定義的業務方法。
適配器模式有類適配器和對象適配器兩種實現:
1、在類適配器模式中,適配器類實現了目標抽象類接口并繼承了適配者類,在目標抽象類的實現方法中調用所繼承的適配者類的方法。
2、在對象適配器模式中,適配器類實現了目標抽象類并定義了一個適配者類的對象實例,在目標抽象類的實現方法中調用適配者類實例的方法。
示例
假如我們手上有一只手機,它只有一個type-c接口,同時手上有一條3.5mm的耳機,想聽音樂的時候就會發現二者不兼容,相較于更換手機或者耳機,一般我們會選擇一條type-c和3.5mm的轉接線來實現最高性價比。
此時將3.5mm耳機比作客戶端(客戶類),它期望得到音樂信號的目標是3.5mm接口(目標抽象類),type-c接口則是手機提供的音樂信號傳輸接口(適配者類),與耳機接頭不兼容,而轉接線(適配器類)可以將type-c接口包裝為耳機可以插入的3.5mm接口,能夠解決手機與耳機的不兼容問題,實現用耳機接收手機播放的音樂信號。
1、定義目標抽象類,即客戶類期望的接口。
public interface ThreePointFiveConn { //一個提供音樂的3.5mm接口 public void playMusic(String connector); }
2、定義適配者類,即需要被包裝的類。
public interface PlayMusicConn { public void playMusicOut(String connector); } public class TypecPlayMusicConn implements PlayMusicConn { //只允許typec接頭插入 public void playMusicOut(String phoneConnType, String musicName) { if("typec".equals(phoneConnType)){ //實現播放音樂功能 System.out.println("playing music with typec Player..." + musicName); }else { System.out.println("error!"); } } } public class LightningPlayMusicConn implements PlayMusicConn { //只允許Lightning接頭插入 public void playMusicOut(String phoneConnType, String musicName) { if("lightning".equals(phoneConnType)){ //實現播放音樂功能 System.out.println("playing music with lightning Player..." + musicName); }else { System.out.println("error!"); } } }
類適配器模式:由于適配器類是適配者類的子類,因此可以在適配器類中重寫適配者類的方法,使得適配器類更具靈活性。
3、構建適配器類,將適配者類PlayMusicConn包裝為目標抽象類ThreePointFiveConn的一個子類。
public class Transverter extends TypecPlayMusicConn implements ThreePointFiveConn { //調用繼承的適配者類的方法 public void playMusic(String musicName) { super.playMusicOut("typec", musicName); } }
4、客戶端類(耳機)使用
public class EarPhone { public static void main(String[] args) { ThreePointFiveConn earPhone = new Transverter(); earPhone.playMusic("Hey Jude"); } }
運行結果:
playing music with typec Player…Hey Jude
- 對象適配器模式:一個對象適配器類可以把多個不同的適配者類及其子類適配到同一個目標抽象類,因此具有更大的兼容性。
3、構建適配器類,將適配者類PlayMusicConn包裝為目標抽象類ThreePointFiveConn的一個子類。
public class Transverter implements ThreePointFiveConn { //定義適配者類的對象實例 private PlayMusicConn playMusicConn; public Transverter(PlayMusicConn playMusicConn){ this.playMusicConn = playMusicConn; } public void playMusic(String musicName) { if(playMusicConn instanceof TypecPlayMusicConn) { playMusicConn.playMusicOut("typec", musicName); }else if(playMusicConn instanceof LightningPlayMusicConn) { playMusicConn.playMusicOut("lightning", musicName); }else { System.out.print("error!"); } } }
4、客戶端類(耳機)使用
public class EarPhone { public static void main(String[] args) { //typec接口手機播放音樂 ThreePointFiveConn earPhone = new Transverter(new TypecPlayMusicConn()); earPhone.playMusic("Hey Jude"); //lightning接口手機播放音樂 ThreePointFiveConn earPhone1 = new Transverter(new LightningPlayMusicConn()); earPhone1.playMusic("Hey Jude"); } }
運行結果:
playing music with typec Player…Hey Jude
playing music with lightning Player…Hey Jude
擴展
除類適配器和對象適配器模式外,還有一種接口適配器模式。接口適配器模式是指在定義適配器時,先將其定義為一個抽象類實現接口,接口中定義了多個抽象方法,定義該適配器的子類時,子類只實現其中的部分抽象方法。
它適用于一個接口不想使用其所有的方法的情況。因此也稱為單接口適配器模式。
public abstract class TransverterInterface implements ThreePointFiveConn { PlayMusicConn playMusicConn = new TypecPlayMusicConn(); public void playMusic(String musicName) { playMusicConn.playMusicOut("typec", musicName); } public void anotherMethod1(){} public void anotherMethod2(){} } public class TransverterInterfaceImpl extends TransverterInterface { public void playMusic(String musicName) { super.playMusic(musicName); } }
總結
適配器模式的主要優點是將目標類和適配者類解耦,增加了類的透明性和復用性,同時系統的靈活性和擴展性都非常好,更換適配器或者增加新的適配器都非常方便,符合“開閉原則”。
適配器模式適用情況包括:系統需要使用現有的類,而這些類的接口不符合系統的需要;想要建立一個可以重復使用的類,用于與一些彼此之間沒有太大關聯的一些類一起工作。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!
原文鏈接:https://blog.csdn.net/sinat_37623490/article/details/120028431