iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0

轉接器模式允許你在不修改現有程式碼的情況下轉換類別的介面,讓原本互不相容的兩個類別合作無間。

生活案例

出國旅遊時,當地的插座和電壓常常與台灣不同,因此經常需要攜帶轉接頭。轉接頭可以將充電器的接頭轉換成適合當地插座的形狀,讓電子設備順利充電。轉接器模式就像轉接頭一樣,可以將一個類別的介面轉換成另一個介面,使原本不相容的兩個類別可以順利合作。

舉個例子

假設你是公司會員系統的負責人。目前,公司使用自制的認證機制來驗證會員身份,然而,這套機制非常老舊且缺乏維護,你打算使用 JWT token 來翻新認證機制,以提升會員系統的安全性。

這是舊的認證機制。

class LegacyToken implements LegacyTokenMethods {
  assign() {
    console.log("Generate legacy token");
  }

  validate() {
    console.log("Validate legacy token");
  }
}

這是新的認證機制。

class JSONWebToken implements JSONWebTokenMethods {
  sign() {
    console.log("Generate JSON Web Token");
  }

  verify() {
    console.log("Validate JSON Web Token");
  }
}

在一般情況下,我們必須翻遍整個應用程式,修改所有與認證機制相關的程式碼。這樣的工程既耗時又費力,一旦有所遺漏還可能導致無法挽回的後果。然而,通過使用轉接器模式,我們可以將新的認證機制轉換為舊機制的介面,減少需要修改的程式碼,降低發生錯誤的風險。

定義舊機制轉接器,將 JWT 認證機制轉為舊機制介面,讓客戶端程式不必修改程式碼就能透過既有介面來操作新機制。

class LegacyTokenAdapter implements LegacyTokenMethods {
  constructor(private jwt: JSONWebToken) {}

	// 讓 JWT 適應舊認證系統的註冊方法
  assign() {
    this.jwt.sign();
  }

	// 讓 JWT 適應舊認證系統的驗證方法
  validate() {
    this.jwt.verify();
  }
}

測試程式。

class ServerTestDrive {
  static main() {
    const server = new Server();

    const legacyToken = new LegacyToken();
    const jwt = new JsonWebToken();
    const adaptedJwt = new LegacyTokenAdapter(jwt);

    const legacyLoginHandler = new LoginHandler(legacyToken);
    const legacyVerifyHandler = new VerifyHandler(legacyToken);
    const jwtLoginHandler = new LoginHandler(adaptedJwt);
    const jwtVerifyHandler = new VerifyHandler(adaptedJwt);

    server.use("/login", legacyTokenLoginHandler);
    server.use("/login/jwt", jwtLoginHandler);
    server.use("/verify", legacyTokenVerifyHandler);
    server.use("/verify/jwt", jwtVerifyHandler);

    console.log("Starting server and responding to routes...");

    server.respond("/login");
    server.respond("/login/jwt");
    server.respond("/verify");
    server.respond("/verify/jwt");
  }
}

ServerTestDrive.main();

輸出結果。

Starting server and responding to routes...
LoginHandler: Handling login request...
Generate legacy token
LoginHandler: Handling login request...
Adapting JWT generation to legacy token format
Generate JSON Web Token
VerifyHandler: Handling token verification request...
Validate legacy token
VerifyHandler: Handling token verification request...
Adapting JWT validation to legacy token format
Validate JSON Web Token

如此一來,我們可以專注於處理核心的認證邏輯,等待新系統穩定後再逐步調整客戶端程式碼。此外,我們還能保留舊的認證系統,在必要時切換回舊的認證機制。

定義

Adapter Pattern

  • 轉接器(Adapter): 使被轉接者適應目標介面
  • 目標介面(Target): 客戶端預期的介面
  • 被轉接者(Adaptee): 被轉接器改變介面的對象

轉接器就如同現實生活中的轉接頭一般,將一個介面封裝成另一個介面,讓原先互不相容的兩個類別可以彼此合作。有了轉接器的幫助,我們不需改變程式的介面也能讓程式互相溝通,既能提升程式的可靠性和穩定性,也有助於外部程式的整合。

總結

  • 轉接器藉由封裝類別去適應另一個類別的介面
  • 轉接器允許你在不改變程式碼的情況下提升程式的相容性
  • 轉接器能夠以安全而有效的方式整合新舊程式碼,介接內外部服務
  • 轉接器必須實現目標介面的所有屬性和方法,目標介面的複雜度決定了轉接器的實作成本

完整範例

https://github.com/chengen0612/design-patterns-typescript/blob/main/patterns/structural/adapter.ts


上一篇
Day 12 - Facade 表象
下一篇
Day 14 - Prototype 原型
系列文
前端也想學設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言