Swift設計模式 – 適配器模式 (Adapter Pattern)


你和我都是熱衷於學習的工程師,我們經常閱讀各種書籍或文章,常常因為一本書寫的實在太好,於是又買了其中提到的其他書籍,我們深深的感受到知識帶來的精神上飽足感。

我們又同時熱愛分享,常常在自己的 Blog 上撰寫讀書心得,在社群網站上分享文章,在生活中又經常與好友推薦與分享自己所閱讀到的好書

而同時我們又是熱愛分享的工程師,我們經常撰寫 Blog,遊走於各種社交平台,到處分享所見所得,還常常舉辦 workshop 活動,我們不只是在獲取知識上得到滿足,我們還在分享的過程中得到了成就感。

由於我們在 Stone City 中的活躍,似乎工程圈的人都認識了我們,所以當 Stone City 市長打算建造一間城市中最大的圖書館時,也找到了我們。


市長打算打造一個城市中最大間的圖書館,取名叫 Stone Library,他希望這間圖書館在初期能夠有最基本的兩種書籍查詢功能,按照書名、分類來查找。

當然,這樣的目標對我們兩個來說還是蠻容易達成的,在接下這個挑戰之後,我們身上產生了一股熱流,連續通宵了七天之後就寫好了。

基本的書籍查詢功能

首先,我們建立一個 StoneLibrary.swift 並且定義了一本書最基本的兩個Property 分別是 name 以及 category,並且規定資料來源必須要實現 books 來獲取所有的書籍,以及通過 name 和 category 來進行 search 的方法。

StoneLibrary.swift

接著我們建立 StoneLibraryDB,所有的書籍放在 books 中,並且提供兩個方法用(searchByName, searchByCategory)來查詢書籍,你和我都很清楚,因為這兩個search方法的實現方式是一樣的,所以我們將其中的方法獨立出來,放在search 方法中。

接著,我們整理好了 ComputerScience 和 Fruit 兩類書籍,並且規定他們要遵循StoneLibraryDB 協議。

StoneLibraryDB.swift

提供一個對外的查詢工具,工具中規範了兩種 SearchType,並且可以在初始化時加入書籍資料 StoneLibraryDB,可以通過books來獲取所有的書籍,通過 search方法來查找書籍。

StoneLibrarySearchTool.swift

在我們完成後拿去給 Stone City 的市長做測試:

我們調用了測試的 code:

看到下面的運行結果,看來是成功了,市長表示非常高興,他已經看到了升遷的希望:D

不過 Stone City 的市長是非常有野心的,他想要打造一個圖書館平台,希望市民能夠通過這一個平台來搜尋所有圖書館的書籍,任何人想要借書都可以通過這個平台,當市民借閱一本書籍時,這本書就會搬運到距離這個市民最近的圖書館,聽起來超方便的對不對?!

然而每一間圖書館的系統都是不一樣的,要把他們都融入自己的系統中真的是一件不容易的事情,而且有一些舊系統,在還沒有全盤了解之前,都不知道是不是可以改動 source code….


整合第一間 Old Library

OldLibrary 是我們需要整合的第一間圖書館,他的歷史非常悠久,至今為止已經服務過幾代人了,剛和這間圖書館的 Devloper 聯繫,他們串了一段 Source Code過來。

並且在 email 中表示,目前他們只剩下一位負責維護的 Developer,如果需要整合,目前來看是沒有時間去修改 Code 的。

看到下面的 source code,目前來說,我們光是繼續維護開發 Stone Library 的系統就已經忙得不可開交,這下子該怎麼整合呢?


適配器模式(Adapter Pattern)

當現有的系統需要繼承一個具有類似功能的新組件,而該組件沒有提供通用接口,並且無法修改改組件時,這時候就可以用上適配器了。

  • 優點:將無法修改 source code 的組件集成到現有的項目中。在使用第三方框架或者利用另一個項目所輸出的數據時,通常會遇到組件之間的兼容問題。
  • 何時應該避免使用:如果可以修改所要集成的組件的 SourceCode 或者可以直接將該組件提供的 Data 直接遷移到現有的應用中的話。(比如我們其實可以直接將 OldLibrary 中的資料 copy 到 StoneLibrary 中)

從長遠來看,數據遷移是個不錯的方式,但有時卻很難快速的完成,但現實生活中常常碰到的是找不到原有的開發工程師配合,又或者沒有足夠的人力投入,所以有時候直接使用適配器模式可以取得一些短期的效益。

適配器模式就很像上面這個轉接頭,我們通過製作一個轉接頭,就可以在不改造設備內部結構的情況下直接使用該設備了。


實現 OldLibraryAdapter

創建適配器的幾個步驟:

  • 創建一個 OldLibraryAdapter,並且讓它遵從 LibraryDataSource 協議
  • Adapter 向 OldLibrary 發送請求,OldLibrary 處理請求內容,將結果返回給Adapter
  • Adapter 將 OldLibrary 返回的結果,轉換成 StoneLibrary 所需要的內容

我們創建了 OldLibraryAdapter.swift 並且讓他遵循 StoneLibrarydataSource 協議,其中我們在實現 books 的獲取,searchByName 以及 SearchByCategory 的過程,實際上是調用 OldLibrary 的一些方法,在獲得需要的資料以後將 Data 轉換成 StoneLibrary 所使用的格式(Book)在返回內容。

OldLibraryAdapter.swift


最後的測試

這時候我們提供給 Stone City 的市長測試時,他可以不用了解 Old Library 的實現情況,而直接使用我們的 OldLibraryAdapter 就可以了!

輸出結果

市長放煙火啦~


最後,在欣賞完煙火以後,可以通過傳送門到 Github 上看看適配器模式的例子

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料