# Design Pattern - Adapter ## 前言 你是否曾經遇過辛辛苦苦開發了一個不錯的程式包,卻因為一點點的差異導致無法被重複應用。 這個差異可能是 5%、10%、20% 左右,但卻造成了整包東西無法被再次使用、整合的情境。 今天在專案中引用一個 A 服務,隔天被告知要更換成 B 服務,幾周後又要改成 C 服務,而來自 A B C 的服務本身或多或少都有差異,造成每一次的改變都必須更動到原本的程式邏輯才能完美契合。 但對於程式碼的維護來說卻是糟糕的處理方式,每一次的更正都必須要跑一次測試。 這就像過去有許許多多不同規格的電線插頭一樣,為了不同的插頭而去更換機械部件的插座,非常不符合效益。 今天要說到的 Adapter 正是後來出現的 "轉接頭",他實現了不同規格仍能對接的期望,避免需要更換插座或是更換插頭的狀況。 ## 主題 **Adapter Pattern** 中文常見名稱 **建造者模式** 屬於 **Structural Design Pattern** 一種常見的設計理念。 目的是幫助工程師在對接服務的時候,避免需要動到對街服務本身的邏輯,從而避免了可能因改動造成的問題。確保了程式本身的獨立與完整。 **優點:** - 底層邏輯與實務邏輯(Adapter層)職責分離,增加底層邏輯的重複使用性 - 符合 S.O.L.I.D 原則 - 高擴展性 **缺點:** - 過度的使用 Adapter Pattern 會增加整體架構的複雜性與可維護性 - 較直接使用底層邏輯來的低效 - 測試的難度較高,錯誤的來源有更多的可能性 Adapter Design Pattern 又分為兩種: - Object Adapter - Class Adapter ## Object Adapter 透過實作指定 Interface 的 Adapter 類,並放入想要轉換的類方式實現調配  [圖片來源於 Adapter Design Pattern Wiki](https://en.wikipedia.org/wiki/Adapter_pattern) ## Class Adapter 透過多重繼承的方式進行調配,適用於 C++、Python,Java 因為不支援多重繼承,故需要改寫成繼承與實作並行的方式實現調配  [圖片來源於 Adapter Design Pattern Wiki](https://en.wikipedia.org/wiki/Adapter_pattern) ## 實行方式 ```java= public class Adapter { public static void main(String [] args){ InitService1 service1 = new Service1Impl(); InitService2 service2 = new Service2Impl(); service1.service_1(); service1.service_2(); service2.service_3(); service2.service_4(); AdapterService1ToService2 adapterService = new AdapterService1ToService2(service1); adapterService.service_3(); adapterService.service_4(); } } interface InitService1{ void service_1(); void service_2(); } class Service1Impl implements InitService1{ @Override public void service_1() { System.out.println("This is Service 1 Service_1()."); } @Override public void service_2() { System.out.println("This is Service 1 Service_2()."); } } interface InitService2{ void service_3(); void service_4(); } class Service2Impl implements InitService2 { @Override public void service_3() { System.out.println("This is Service 2 Service_3()."); } @Override public void service_4() { System.out.println("This is Service 2 Service_4()."); } } class AdapterService1ToService2 implements InitService2 { private InitService1 service1Impl; public AdapterService1ToService2(InitService1 initService1){ this.service1Impl = initService1; } @Override public void service_3(){ /* code ... */ System.out.println("This is Adapter."); service1Impl.service_1(); /* code ... */ } @Override public void service_4(){ /* code ... */ System.out.println("This is Adapter."); service1Impl.service_2(); /* code ... */ } } ``` ``` Execute Results: This is Service 1 Service_1(). This is Service 1 Service_2(). This is Service 2 Service_3(). This is Service 2 Service_4(). This is Adapter. This is Service 1 Service_1(). This is Adapter. This is Service 1 Service_2(). ``` 範例中有 **InitService1**、**InitService2** 兩介面,與實作介面的實體 **Service1Impl**、**Service2Impl** Kai 這邊建立一個將 Service1 轉為 Service2 的 Adapter 類別 **AdapterService1ToService2**,由於目標是轉成 Service2,故需實作 InitService2 除了實作介面的方法外,還包含將 Service1 放入的方法,在使用上就可以透過放入 Service1 的方式對接 Service2 的服務了 :::danger 用一句話介紹 Adapter Pattern: **一個轉接頭概念的設計模式** ::: 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Design Pattern`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up