設計模式 – 適配器模式詳解
- 2020 年 3 月 27 日
- 筆記
適配器模式
生活中,充電插頭有兩腳的、三腳的,還有圓形的,如果想使這些插頭都能工作,就需要一個多功能適配器
基本介紹
適配器模式(Adapter Pattern)屬於結構性模式,它可以將某個類的接口轉換為客戶端期望的另一個接口表示,主要目的是兼容性,讓原本因接口不匹配不能一起工作的兩個類可以協同工作,其別名為包裝器(Wrapper)。適配器模式主要分為三類:類適配器模式、對象適配器模式、接口適配器模式。
工作原理
- 讓原本接口不兼容的類可以兼容
- 從用戶的角度看不到被適配者,是解耦的
- 用戶調用適配器轉化出來的目標接口方法,適配器去再調用被適配者的相關接口方法
類適配器模式
實現原理
Adapter 類繼承 src 類,實現 dst 接口,完成 src 對 dst 的適配。
案例
插座(Voltage220V)的輸出電壓是220V,充電插頭(Voltage5V)輸出電壓是5V,這時候就需要一個適配器(VoltageAdapter)轉換電壓,才能給手機(Phone)充電
代碼實現
電源輸出電壓為220V
public class Voltage220V { public int output220V() { int src = 220; System.out.println("電源輸出" + src + "V"); return src; } }
充電器輸出電壓為5V
public interface Voltage5V { int output5V(); }
適配器需要將220V轉為5V
public class VoltageAdapter extends Voltage220V implements Voltage5V { @Override public int output5V() { int src = super.output220V(); int dst = src / 44; System.out.println("轉換為" + dst + "V"); return dst; } }
手機接收5V電壓,判斷電壓是否為5V
public class Phone { public static void charging(Voltage5V voltage5V){ int v = voltage5V.output5V(); if(v == 5){ System.out.println("接收電壓為5V,正常充電"); }else if(v > 5){ System.out.println("電壓高於5V,無法充電"); } } }
測試方法
@Test public void test01(){ System.out.println("====類適配器模式===="); Phone.charging(new VoltageAdapter()); }
運行結果
====類適配器模式==== 電源輸出220V 轉換為5V 接收電壓為5V,正常充電
分析
- 由於 Java 是單繼承機制,所以類適配器模式有一定的局限性
- src 類的方法再 Adapter 中都會暴露出來,增加了使用的成本
- 由於繼承了 src 類,所以它可以重寫父類方法,使 Adapter 的靈活性增強了
對象適配器模式
實現原理
基本的思路和類的適配器模式相同,只是將 Adapter 類做修改,使用聚合關係替代繼承關係
代碼實現
沿用前面的代碼,新建一個適配器,只是將原來的 Adapter 繼承 src 類換為聚合的關係
public class VoltageAdapter2 implements Voltage5V { private Voltage220V voltage220V; public VoltageAdapter2(){ this.voltage220V = new Voltage220V(); } @Override public int output5V() { int src = this.voltage220V.output220V(); int dst = src / 44; return dst; } }
測試方法
@Test public void test02(){ System.out.println("====對象適配器模式===="); Phone.charging(new VoltageAdapter2(new Voltage220V())); }
運行結果
====對象適配器模式==== 電源輸出220V 轉換為5V 接收電壓為5V,正常充電
接口適配器模式
接口適配器模式也可稱為缺省適配器模式,當不需要實現接口的全部方法時,可先設計一個抽象類實現接口,並為該接口的每個方法都提供一個默認實現,那麼該抽象類的子類就可以有選擇的覆蓋父類的某些方法來實現需求。
適用於一個接口不想使用其所有的方法的情況
代碼實現
寫一個接口,裏面定義一些方法
public interface InterfaceMethod { void m1(); void m2(); void m3(); void m4(); }
一個抽象類,實現該接口
public abstract class AbstractAdapter implements InterfaceMethod { @Override public void m1() { } @Override public void m2() { } @Override public void m3() { } @Override public void m4() { } }
測試方法
@Test public void test(){ //使用匿名內部類的方式 AbstractAdapter adapter = new AbstractAdapter() { @Override public void m1() { System.out.println("我要用m1方法"); } }; adapter.m1(); }
運行結果
我要用m1方法
總結
-
三種命名方式是根據 src 是以怎樣的形式給到 Adapter (在Adapter里的形式)來命名的。
-
類適配器:以類給到,在 Adapter 里,就是將 src 當做類,繼承
-
對象適配器:以對象給到,在 Adapter 里, 將 src 作為一個對象,持有
-
接口適配器:以接口給到,在 Adapter 里,將 src 作為一個接口,實現
-
-
Adapter模式最大的作用還是將原本不兼容的接口融合在一起工作。