适配器模式(Adapter Pattern)
一、定義
適配器模式(Adapter Pattern):結構型模式之一,將一個類的接口轉換成客戶希望的另一個接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些類可以一起工作。
二、UML類圖
三、角色職責
- 目標角色(Target):該角色定義把其他類轉換為何種接口,也就是我們的期望接口。
- 源角色(Adaptee):你想把誰轉換成目標角色,這個“誰”就是源角色,它是已經存在的、運行良好的類或對象。
- 適配器角色(Adapter):適配器模式的核心角色,其他兩個角色都是已經存在的角色,而適配器角色是需要新建立的,它的職責非常簡單:通過繼承或是類關聯的方式把源角色轉換為目標角色。
四、代碼實現
前言:舉個栗子,我今天買了機票,飛到香港迪士尼去游玩,晚上回到了酒店,想給我的筆記本電腦充電,但這時我發現,香港的插座是英式三角插座,我的充電器插不進去。這時我們就可以使用適配器模式,進行適配。
-
類適配器:適配器通過類來實現,以類來繼承和實現接口的方式,來獲取被適配類的信息并轉換輸出重寫到適配接口。
中式插座(目標角色 Target)
@AllArgsConstructor @Data public class ChineseStandard {public String getChineseStandard() {return "中式插座";} }英式插座(源角色 Adaptee)
public interface BritishStandard {String getBritishStandard(); }插座適配器(適配器角色 Adapter)
public class StandardAdapter extends ChineseStandard implements BritishStandard {@Overridepublic String getBritishStandard() {return this.getChineseStandard();} }筆記本電腦(客戶端 Client)
public class Notebook {public void charge(BritishStandard britishStandard) {if ("中式插座".equals(britishStandard.getBritishStandard())) {System.out.println("充電成功!");} else {System.out.println("充電失敗!");}} }測試類
public class AdapterTest {public static void main(String[] args) {// 充電成功!new Notebook().charge(new StandardAdapter());} } -
對象適配器:通過實例對象(構造器傳遞)來實現適配器,而不是再用繼承,其余基本同類適配器。
我么們將插座適配器就行修改即可
@AllArgsConstructor public class StandardAdapter implements BritishStandard {private ChineseStandard chineseStandard;@Overridepublic String getBritishStandard() {return chineseStandard.getChineseStandard();} }測試類
public class AdapterTest {public static void main(String[] args) {// 充電成功!new Notebook().charge(new StandardAdapter(new ChineseStandard()));} }如果我們的源目標接口中還有一些其他我們不需要的方法,我們并不想去實現它,我們就可以將適配器作為一個抽象類,當我們實現適配器抽象類的時候只要重寫我們需要的方法即可。這時候我們就用到了接口適配器。
-
接口適配器:當不需要全部實現接口提供的方法時,可先設計一個抽象類實現接口,并為該接口中每個方法提供一個默認實現(空方法),那么該抽象類的子類可有選擇地覆蓋父類的某些方法來實現需求。
英式插座(源角色 Adaptee)
public interface BritishStandard {String getBritishStandard();String getTypeC();String getUSB(); }插座適配器(適配器角色 Adapter)
@AllArgsConstructor public abstract class StandardAdapter extends ChineseStandard implements BritishStandard {@Overridepublic String getBritishStandard() {return null;}@Overridepublic String getTypeC() {return null;}@Overridepublic String getUSB() {return null;} }測試類
public class AdapterTest {public static void main(String[] args) {StandardAdapter standardAdapter= new StandardAdapter() {@Overridepublic String getBritishStandard() {return new ChineseStandard().getChineseStandard();}};// 充電成功!new Notebook().charge(standardAdapter);} }
五、源碼分析
我們先來看一下Spring MVC的工作原理
可以看出Spring MVC中的適配主要執行Controller的請求處理方法。在Spring MVC中,DispatcherServlet作為用戶,HandlerAdapter作為期望接口(目標角色 Target),Controller則為源角色(Adaptee)。Spring MVC中的Controller種類眾多,不同類型的Controller通過不同的方法來對請求進行處理。
我們首先看一下HandlerAdapter接口
Spring MVC提供的Controler如下。
Spring MVC提供的Adapter如下。
該接口的每一個Controller都有一個適配器與之對應,這樣的話,每自定義一個Controller需要定義一個實現HandlerAdapter的適配器。
我們進入DispatcherServlet類,查看是如何獲得適配器的。
當Spring容器啟動后,會將所有定義好的適配器對象存放在一個List集合中,當一個請求來臨時,DispatcherServlet會通過 handler的類型找到對應適配器,并將該適配器對象返回給用戶,然后就可以統一通過適配器的handle()方法來調用Controller中的用于處理請求的方法。通過適配器模式我們將所有的Controller統一交給 HandlerAdapter 處理,免去了寫大量的 if-else 語句對 Controller進行判斷,也更利于擴展新的Controller類型。
六、優缺點分析
類適配器
優點:可以根據需求重寫Adaptee類的方法,使得Adapter的靈活性增強了。
缺點:有一定局限性。因為類適配器需要繼承Target類,而Java是單繼承機制,所以要求Adaptee類必須是接口。
對象適配器
優點:同一個Adapter可以把Adaptee類和他的子類都適配到目標接口。
缺點:需要重新定義Adaptee行為時,需要重新定義Adaptee的子類,并將適配器組合適配。
接口適配器
優點:可以靈活方便的選擇性重寫接口方法。
缺點:由于是匿名內部類的形式,所以不利于代碼復用。
七、適用場景
- 系統需要復用現有類,而該類的接口不符合系統的需求,可以使用適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
- 多個組件功能類似,但接口不統一且可能會經常切換時,可使用適配器模式,使得客戶端可以以統一的接口使用它們。
八、總結
適配器模式將現有接口轉化為客戶類所期望的接口,實現了對現有類的復用,它是一種使用頻率非常高的設計模式,在軟件開發中得以廣泛應用,Spring等開源框架、驅動程序設計(如JDBC中的數據庫驅動程序)中也都使用了適配器模式。
總結
以上是生活随笔為你收集整理的适配器模式(Adapter Pattern)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: aes解密流程图_aes流程图(apqp
- 下一篇: Qt视频直播软件--项目实战(Day6)