精讀《設計模式 - Adapter 適配器模式》

Adapter(適配器模式)

Adapter(適配器模式)屬於結構型模式,別名 wrapper,結構性模式關注的是如何組合類與對象,以得到更大的結構,咱們日常工做大部分時間都在與這種設計模式打交道。前端

意圖:將一個類的接口轉換成客戶但願的另外一個接口。Adapter 模式使得本來因爲接口不兼容而不能在一塊兒工做的那些類能夠一塊兒工做。git

這個設計模式的意圖很好懂,就是把接口不兼容問題抹平。注意,也僅僅能解決接口不一致的問題,而不能解決功能不一致的問題。github

舉例子

若是看不懂上面的意圖介紹,沒有關係,設計模式須要在平常工做裏用起來,結合例子能夠加深你的理解,下面我準備了三個例子,讓你體會什麼場景下會用到這種設計模式。sql

接口轉換器

插座的種類不少,咱們都用過許多適配器,將不一樣的插頭進行轉換,能夠在不替換插座的狀況下正常使用。typescript

USB 接口轉換也一樣精彩,有將 TypeC 接口轉換爲 TypeA 的,也有將 TypeA 接口轉換爲 TypeC 的,支持雙向轉換。數據庫

接口轉換器就是咱們在生活中使用到的適配器模式,由於廠商並無生產一個新的插座,咱們也沒有由於接口不適配而換一個手機,一切只須要一個接口轉換器便可,這就是運用設計模式的收益。設計模式

數據庫 ORM

ORM 屏蔽了 SQL 這一層,帶來的好處是不須要理解不一樣 SQL 語法之間的區別,對於通用功能,ORM 會根據不一樣的平臺,好比 Postgresql、Mysql 進行 SQL 的轉換。微信

對 ORM 來講,屏蔽不一樣平臺的差別,就是利用適配器模式作到的。app

API Deprecated

當一個普遍使用的庫進行了含有 break change 的升級時,每每要留給開發者足夠的時間去升級,而不能升級後就直接掛掉,所以被廢棄的 API 要標記爲 deprecated,而這種被廢棄標記的 API 的實際實現,每每是使用新的 API 替代,這種場景正是使用了適配器模式,將新的 API 適配到舊的 API,實現 API Deprecated。框架

意圖解釋

上面三個例子都知足下面兩個條件:

  1. API 不兼容:由於接口的不一樣;數據庫 SQL 語法的不一樣;框架 API 的不一樣。
  2. 但能力已支持:插座都擁有充電或讀取能力;不一樣的 SQL 都擁有查詢數據庫能力;新 API 覆蓋了舊 API 的能力。

這樣就能夠經過適配器知足 Adapter 的意圖:

意圖:將一個類的接口轉換成客戶但願的另外一個接口。Adapter 模式使得本來因爲接口不兼容而不能在一塊兒工做的那些類能夠一塊兒工做。

結構圖

適配器的實現分爲繼承與組合模式。

下面是名詞解釋:

  • Adapter 適配器,把 Adeptee 適配成 Target
  • Adaptee 被適配的內容,好比不兼容的接口。
  • Target 適配爲的內容,好比須要用的接口。

繼承:

適配器繼承 Adaptee 並實現 Target,適用場景是 AdapteeTarget 結構相似的狀況,由於這樣只須要實現部分差別化便可。

組合:

組合的拓展性更強,但工做量更大,若是 TargetAdaptee 結構差別較大,適合用組合模式。

代碼例子

下面例子使用 typescript 編寫。

繼承:

`interface ITarget {
// 標準方式是 hello
hello: () => void
}
class Adaptee {
// 要被適配的類方法叫 sayHello
sayHello() {
console.log('hello')
}
}
// 適配器繼承 Adaptee 並實現 ITarget
class Adapter extends Adaptee implements ITarget {
hello() {
// 用 sayHello 對接到 hello
super.sayHello()
}
}`

組合:

`interface ITarget {
// 標準方式是 hello
hello: () => void
}
class Adaptee {
// 要被適配的類方法叫 sayHello
sayHello() {
console.log('hello')
}
}
// 適配器繼承 Adaptee 並實現 ITarget
class Adapter implements ITarget {
private adaptee: Adaptee
constructor(adaptee: Adaptee) {
this.adaptee = adaptee
}
hello() {
// 用 adaptee.sayHello 對接到 hello
this.adaptee.sayHello()
}
}`

弊端

使用適配器模式自己就多是個問題,由於一個好的系統內部不該該作任何僑界,模型應該保持一致性。只有在以下狀況才考慮使用適配器模式:

  1. 新老系統接替,改形成本很是高。
  2. 三方包適配。
  3. 新舊 API 兼容。
  4. 統一多個類的接口。通常能夠結合工廠方法使用。

總結

適配器模式也複合開閉原則,在不對原有對象改造的前提下,構造一個適配器就能完成模塊銜接。

適配器模式的實現分爲類與對象模式,類模式用繼承,對象模式用組合,分別適用於 AdapteeTarget 結構類似與結構差別較大的場景,在任何狀況下,組合模式都是靈活性最高的。

最後用一張圖歸納一下適配器模式的思惟:

討論地址是: 精讀《設計模式 - Adapter 適配器模式》· Issue #279 · dt-fe/weekly

若是你想參與討論,請 點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。

關注 前端精讀微信公衆號

版權聲明:自由轉載-非商用-非衍生-保持署名( 創意共享 3.0 許可證

本文使用 mdnice 排版

相關文章
相關標籤/搜索