深入淺出設計模式(Design Pattern)-轉接器模式(7-Adapter-Pattern)

Ben
生活的各種可能性
Jan 30, 2024
photo by Call Me Fred

看到這張圖片是不是用腳指頭上的指甲都想的出來要介紹什麼啊,這篇要來介紹轉接器模式(Adapter Pattern)。

轉接器模式(Adapter Pattern)

定義:可以將一個類別的介面轉換成用戶端預期的另一個介面。轉接器可以讓介面不相容的類別合作無間。

我們先來看看我們這次碰到的問題

情境:我們目前有一個既有的系統,但我們現在必須將廠商的系統整合進我們的系統裡,但廠商與我們既有的介面不一樣,所以無法接在一起,但我們又不想為了這個問題修改我們或是廠商(不容許修改)的程式碼,那我們有沒有什麼辦法能在這個狀況下不編寫額外的程式碼將它們整合起來呢?

我們來看看一個簡單的範例

// 轉接器介面(client呼叫的對象)
interface IteratorAdapter {
hasNext(): void;
next(): void;
remove(): void;
}

// 適應者(被轉接的對象)介面
interface EnumeratorAdaptee {
hasMoreElements(): void;
nextElement(): void;
delete(): void;
}

// 實作適應者(被轉接的對象)
class EnumeratorAdaptee implements EnumeratorAdaptee {
public hasMoreElements(): void {
console.log("call hasMoreElements");
}

public nextElement(): void {
console.log("call nextElement");
}

public delete(): void {
console.log("call delete");
}
}

// 實作轉接器
class EnumerationIterator<T extends EnumeratorAdaptee> implements IteratorAdapter {
enumerator: T;

// 建構式接受一個被轉接的對象
constructor(enumerator: T) {
this.enumerator = enumerator;
}

// 將行為hasNext委託給接受的對象
public hasNext(): void {
this.enumerator.hasMoreElements();
}

// 將行為next委託給接受的對象
public next(): void {
this.enumerator.nextElement();
}

// 將行為remove委託給接受的對象
public remove(): void {
this.enumerator.delete();
}
}

const enumeratorAdaptee = new EnumeratorAdaptee();
const enumerationIterator = new EnumerationIterator(enumeratorAdaptee);
enumerationIterator.hasNext();
enumerationIterator.next();
enumerationIterator.remove();

在上方範例中我們有個轉接器介面(IteratorAdapter)以及被轉接的對象(EnumeratorAdaptee),它們迭代的方式不太一樣,我們的目標是在不影響客戶端(不改變客戶端)的狀況下整合它們。

首先我們會先實作被轉接的對象,再將被轉接的對象做為參數傳給轉接器,而轉接器則會幫我們轉接這個對象,也會將實際的請求委託給被轉接的對象。

藉由這樣的方式我們就能將各種不同的介面轉換成相同的介面並提供給client端使用。

我們來看一下它們之間的關係

關係示意圖

Client使用Adapter的方式

  1. 用戶端使用目標介面來呼叫轉接器的一個方法,來對轉接器發出一個請求。
  2. 轉接器使用被轉接者的介面,將請求轉換成一個或多個針對被轉接者的呼叫。
  3. 用戶端接收呼叫的結果,但是它不知道有個轉接器在過程中進行轉換。

我們可以用這個模式來建立一個進行轉換的Adapter(轉接器),來讓用戶端使用不相容的介面。轉接器可以解開用戶端和已經實作好的介面之間的耦合關係,當我們知道介面可能隨時改變時,可以用轉接器來封裝那個改變,這樣就不需要再面對不同介面時修改用戶端

重點提示

  • 如果你需要使用既有的類別,但是它的介面不是你需要的,那就使用轉接器。
  • 製作轉接器可能需要少量的工作,也可能需要大量的工作,這取決於目標介面的大小與複雜度。
  • 轉接器模式有兩種,物件轉接器與類別轉接器。類別轉接器需要使用多重繼承。
  • 轉接器藉著包裝物件來改變它的介面。

結語

在前面的許多的章節中,也巧妙的應用了委託與組合的方式來封裝物件並讓本來耦合的關係解耦合,這篇的轉接器模式也是應用這樣的方式來達成我們上述情境中的需求。而自己也在這篇的內容當中對各種情境適合的方式以及做法有更深一層的理解。

下一篇要介紹與轉接器模式一樣都是改變介面的模式:門面模式(Facade Pattern)

這篇就到這邊瞜,如果有任何問題歡迎留言給我,喜歡的話也別忘了clap起來唷。

--

--