Adapter 適配器模式

動機

適配器模式是類和對象之間的適配。同現實生活中的適配器一樣,它用于兩個物體間的接合和橋接?,F實生活里我們有電源適配器,相機的內存卡適配器等。或許每個人都見過一些內存卡的適配器。如果你不能將相機的內存卡插入你的筆記本上, 你就可以用一個適配器。你將相機的內存卡插到適配器上,然后再將適配器插到筆記本插槽上。這樣就可以了, 灰常簡單。

那在軟件開發中,它是怎么樣的? 其實也差不多。你可以設想一下,手頭有一個類,然后你想獲得某種類型的對象,但是你拿到的這個對象雖然提供了一樣的特性,但是暴露出來的接口是不一樣的。當然,你想要同時使用它們兩個,所以你不要再實現其中的一個,而且你也不想改變現有的類,那么為什么不弄個適配器呢?

目的

  • 將一個類的接口轉換成客戶端期望的另一個接口
  • 適配器使得原本由于接口兼容性問題不能一起工作的類能一起工作

實現

adapter uml

參與適配器模式的類和對象:

  • Target 定義 Client 使用的領域特定接口
  • Adapter 將 Adaptee 接口適配成 Target 接口(實現/泛化 Target,并在內部調用 Adaptee)
  • Client 同遵循 Target 接口定義的對象一起工作

適用場景 & 例子

使用場景

  • 你有一個的類(Target),它調用一個接口中的定義的方法,同時你還有一個未實現這個接口的類(Adapter),不過后者實現了應該通過這個接口調用到前者的操作。你可以不用改變現有代碼。適配器會實現這個接口并且作為這兩個類的橋梁。
  • 為了使功能通用而基于通用接口編寫一個類 (Target),但是有些實現類(一般是現有代碼中的類)并沒有實現 Target 要使用的這個接口。
    從現實生活到軟件適配,適配器隨處可見 。

例子

  • 軟件開發之外的適配器模式
    電源適配器、讀卡器和適配器等
  • 軟件開發中的適配器模式
    用于采用第三方類庫和框架的 Wrappers - 大多數使用第三方類庫的應用都會使用適配器作為中間層來將自身從外部類庫中解耦。如果要使用新的類庫,只需要提供針對這個新類庫的適配器而不用修改應用的現有代碼。

具體問題和實現

對象適配器 - 基于委托
對象適配器是適配器模式的經典例子,uml圖如上。它使用組合,Adaptee 將調用委托給 Adapter(與擴展 Adaptee 的 Adapter 不同, 這個Adapter 實現 Target 所需接口 或 擴展 Target 類)。這個行為給了我們幾個優于類適配的優點(不過,類適配器可以應用于允許多繼承的語言中)。主要優點是 adapter 不單適配 adaptee , 還能適配 adaptee 的所有子類。對于 adaptee 的所有子類有個小小的限制: 不能有新方法,因為這邊使用的是委托。所以,對于每個新方法,也要同時修改或擴展適配器 Adapter。對象適配器主要的缺點是為了將請求所有需要委托給 Adapter 你的寫所有的相關代碼。

類適配器 - 基于多繼承


類適配器適用于支持多繼承的語言(Java、C#或PHP不支持多繼承)。這樣,這種適配器就不能輕易用與 Java,C# 和 VB.NET。類適配器使用繼承而不是組合。也就是說,它不是將對 adaptee 的調用委托出去,而是繼承 adaptee。總的來說它必須同時繼承 Target 和 Adaptee 。 這有以下優缺點:

  • 類適配器適配特定的 Adaptee 類。 對于它繼承的類,如果有其他子類,則這些子類不能用現有的 Adapter 適配。
  • 類適配器不需要對象適配中要寫的那些的代碼。
    如果 Target 是由接口而不是類來表示的,那么我們就能談論 “類”適配器了,因為我們能實現任意多的接口。 Java、C# 或 PHP等單繼承語言就可以按如下用例圖實現 “類適配器”了。


適配器 Adapter 要做到什么程度?

這個問題有個非常簡單的回答:為了適配要做多少就應該做多少(好像挺廢話的)。如果 Target 和 Adaptee 很相似的話,Adapter 只需要將請求從 Target 委托到 Adaptee 就可以了。如果兩者不相似的話,Adapter 就得轉換兩者之間的數據結構,然后再實現 Target 所要求的但是 Adaptee 沒實現的操作。

雙向適配器

雙向適配器是那些同時實現 Target 和 Adaptee 的接口。在新系統中已適配的對象可以作為 Target 管理 Target 類,也可以作為 Adaptee 來處理 Adaptee 類?;谶@種思路,我們的適配器可以實現 n 個接口,適配 n 個系統。雙向適配器和多向適配器很難在不支持多幾次的系統中實現。如果適配器要擴展 Target 類的話,它就不能再擴展其他類,如 Adaptee,所有 Adaptee 就只能是接口,然后所有的調用都要由 Adapter 委托到 Adaptee 對象。

適配器模式和策略模式

在很多場景下適配器模式可以替代策略模式。如果我們有幾個實現相同功能的模塊,為它們寫了實現相同接口的適配器。由于它們實現了相同的接口,我們能輕易地在運行時替換適配器對象。

示例代碼:https://github.com/minorpoet/design-patterns/tree/master/Adapter

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容