20個主題學會設計模式 — (二)萬能轉接器Adapter模式

ㄧ、理解Adapter

Adapter是一種常見的設計模式,它存在的主要目的是想讓兩種東西可以互相適合,舉例來說,我想讓我的電腦投影到大螢幕,但我的電腦並沒辦法「直接」跟大螢幕相接,必須透過HDMI或VGA的轉接頭才能接上,那麼這個轉接頭在做的事情就跟Adapter類似,可以將它想像成串接兩個獨立事務的一個媒介。

在我們的程式當中,並不是所有程式都能直接使用,需要經過一些轉換才可以使用,用來填補“現有的程式”和“新的程式需求”之間差異的設計模式就是Adapter模式,常會有人把Adapter稱為Wrapper模式,意即將現有的程式包裝過後讓新的需求也能夠使用。

二、貓狗叫聲例子來實現Adapter

假設我們目前擁有兩個已經完成測試好的class叫做CatSound,DogSound,分別會Print出狗跟貓的叫聲。

可以看到裡面的方法看起來是沒有什麼關係,但現在我們有個需求,我們希望用戶在使用這兩個類時,不要直接使用它,而是通過Print介面來使用它們,而我們的Print介面如下:

而我們希望讓客戶達成的目的為,用一個Print創建不同的實體類別,但都能調用printSound這個方法,像下面這樣使用,此時PrintCatSound,PrintDogSound這兩個類就是我們的Adapter。

這時候問題來了,我們要怎麼實現PrintCatSound及PrintDogSound這兩個實體類呢?

三、Adapter的兩種實現方法

(1) 使用繼承(Extend)

PrintDogSound

上圖中的程式非常簡單,我們聲明了一個實現類去繼承DogSound,並規定要實現Print介面,因爲繼承的關係我們可以在printSound這個方法直接調用父類的方法。

(2)使用委託(Delegation)

第二種方式是使用委託的方式,也就是在PrintCatSound類中,引用CatSound來使用它的meow方法:

效果是一樣的,區別在於如果原先的類(CatSound)中有很多方法在新的類中都要使用到,那麼用繼承比較合適,若原先的類中有一百個方法,但你新的類中只會使用到一個,那麼就能用委託這種做法,只調用自己想用的。

如此一來在Main主程式中,我們能夠直接使用Print介面中明確定義的printSound方法,用戶將不用再關注到DogSound中的bark方法,CatSound中的meow方法,這就是Adapter的好用地方,我們很完美利用了以前曾有的類別,並創建了新的類別去使用以前類別中的方法,對於DogSound,CatSound完全無需進行修改。

四、Adapter的應用場景

你可能會想說,上面這個好麻煩,為什麼不能直接使用實體類CatSound或DogSound就好,如之前所說,很多時候我們並不是從零開始打造一個類別,我們會經常使用到舊有的類別,假設舊的類別已經經過千錘百鍊,測試也都測試過了,幾乎沒有Bug時,且還被其他程式使用,那麼我們就不應該改變舊有的類別,而是創建一個新的類別(Adapter)來適配現在的新需求,如此一來程式運行如果出錯,也能很好定位是我們新創建的類的問題。

完全不改變現有程式的前提下使現有的程式適應新的API就是Adapter的核心

今天就跟大家分享到這邊,謝謝你們的觀看!

文章Github連結:

我是Andy,謝謝你看完這篇文章,如果文章有幫助到你的話,希望不吝於幫我拍手 🙌🙌

假設今天你們公司中有個大神寫了一個神之類別,裡面的程式質量、效率都極高,你們的公司同仁都使用了這個類許久,但有天突然有個需求,老闆希望你開發另一個類,大多內容跟這個神之類別相似,但又額外添加了一些需求,此時你會去更改大神寫的這個類,還是自己寫一個一樣的類

--

--

Andy Cheng
Andy的趣味程式練功坊

若能將學到的知識轉化為易懂的文章,才能算是真正學會。這是我創建這個帳號的初衷。