轉接器模式

📢 本文由 gemini-2.5-flash 翻譯

轉接器模式 (Adapter Pattern) 類別結構型模式 / 物件結構型模式

意圖

將一個類別的介面轉換成客戶端期望的另一個介面。轉接器模式使得原本因介面不相容而無法協同運作的類別,能夠一起工作。

結構

  1. 類別轉接器使用多重繼承來匹配一個介面與另一個介面。

image

  1. 物件轉接器仰賴於物件組合。

image

其中:

  • Target 定義客戶端 (Client) 使用的與特定領域相關的介面。
  • Client 與符合 Target 介面的物件協同運作。
  • Adaptee 定義一個已經存在的介面,此介面需要被轉接。
  • Adapter 將 Adaptee 的介面與 Target 介面進行轉接。

適用性

轉接器模式適用於:

  • 想使用一個已經存在的類別,但其介面不符合需求。
  • 想建立一個可重複使用的類別,此類別能與其他不相關或無法預期的類別(亦即那些介面可能不一定相容的類別)協同運作。
  • (僅適用於物件轉接器)想使用一個已經存在的子類別,但不可能對每一個子類別都進行子類化來匹配其介面。物件轉接器可以轉接其父類別的介面。

範例 1

某軟體系統中,已設計並實作了用於顯示地址資訊的類別 Address,現要求提供基於荷蘭語的地址資訊顯示介面。為了實作此需求並考量到日後可能還會出現新的語言介面,決定採用轉接器模式來實作,類別圖如下:

适配器模式-例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Adapter {
    public static void main(String[] args) {
        Address address = new Address();
        DutchAddress dutchAddress = new DutchAddressAdapter(address);
        System.out.println("The DutchAddress");
        test(dutchAddress);
    }
    
    static void test(DutchAddress dutchAddress){
        dutchAddress.plaats();
        dutchAddress.postcode();
        dutchAddress.straat();
    }
}

class Address{
    public void street(){/* 程式碼省略 */}
    public void zip(){/* 程式碼省略 */}
    public void city(){/* 程式碼省略 */}
}

class DutchAddress{
    public void straat(){/* 程式碼省略 */}
    public void postcode(){/* 程式碼省略 */}
    public void plaats(){/* 程式碼省略 */}
}

class DutchAddressAdapter extends DutchAddress{
    private Address address;
    public DutchAddressAdapter(Address address){
        this.address=address;
    }

    @Override
    public void straat() {
        address.street();
    }

    @Override
    public void postcode() {
        address.zip();
    }

    @Override
    public void plaats() {
        address.city();
    }
}

範例 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 因 Java 不支援多重繼承,以下為物件轉接器
public class main{
     public static void main(String[] args) {
        Target target = new Adapter();
        target.Request();
    }
}

class Target{
    public void Request(){
        System.out.println("哈囉");
    }
}

class Adapter extends Target{
    private Adaptee a = new Adaptee();

    @Override
    public void Request(){
        a.SpecificRequest();
    }
}

class Adaptee{
    public void SpecificRequest(){
        System.out.println("嗨");
    }
}