適配器在生活中很常見秕脓,例如電源適配器雕旨、USB串口轉接設備等,它們本質上是完成接口轉換的功能悲柱。在編程領域上锋喜,模擬適配器完成接口轉換的一種解決方案叫做適配器模式。
在編程中免不了使用別人的API豌鸡,如果別人提供的API與自己期待的API存在不同的話嘿般,可以使用適配器模式把別人提供的API轉換成自己的所期待的API,這樣一來別人的代碼和自己的代碼都不需要變動涯冠。再者炉奴,日后API有所變動的話,只需要更改或替換適配器即可蛇更,這樣的解決方案符合開閉原則瞻赶,能夠大大提高代碼的可維護性。
在適配器模式中有三個角色派任,target
即所期待的使用對象砸逊,也是適配器所轉換的目標,adapter
即適配器掌逛,完成接口轉換的功能师逸,adaptee
即被轉換的對象。具體的實現(xiàn)可以通過繼承或對象委派來實現(xiàn)颤诀,通過繼承實現(xiàn)的叫做類適配器字旭,通過對象委派實現(xiàn)的叫做對象適配器对湃,而在JS中往往通過一個函數(shù)就可以完成接口的轉換功能。
通過繼承實現(xiàn)適配器
下面是一個第三方庫:
class Painter {
rect() {
console.log('畫矩形')
}
circle() {
console.log('畫圓形')
}
}
module.exports = Painter
而使用者MyPainter
期望的API如下:
interface IMyPainter {
rect():void;
circle():void;
line():void; // 希望有一個畫直線的方法
}
由于第三方API沒有提供畫直線方法遗淳,但是又想使用第三方庫的畫矩形和畫圓形的方法拍柒,所以寫一個適配器來擴展第三方的API完成適配:
class PainterAdapter extends Painter {
line() {
console.log('畫直線')
}
}
使用時:
const myPainter = new PainterAdapter()
myPainter.line();
myPainter.rect();
通過對象委派實現(xiàn)適配器
假設使用者MyPainter
期望的API如下:
interface IMyPainter {
drawRect():void;
drawCircle():void;
}
可以看到同樣的功能在第三方庫已有實現(xiàn),但是API不太一樣屈暗,所以可以使用對象委派的方式適配第三方庫
class PainterAdapter {
constructor() {
this._painter = new Painter()
}
drawRect(...args) {
return this._painter.rect(...args)
}
drawCircle(...args) {
return this._painter.circle(...args)
}
}
使用時
const myPainter = new PainterAdapter()
myPainter.drawRect()
myPainter.drawCircle()
缺省適配器
當你對別人提供的API或數(shù)據(jù)不太放心的時候拆讯,可以使用缺省適配器為別人提供的API或數(shù)據(jù)設置一個默認值,這樣就不怕別人提供的格式不規(guī)范導致代碼出錯养叛。
假設你希望使用的接口還是下面這個
interface IMyPainter {
rect():void;
circle():void;
line():void; // 希望有一個畫直線的方法
}
但是你不確定第三方API是否真的提供了相應的方法种呐,你可以寫一個缺省適配器使得你使用的時候總有一個默認方法:
class DefaultPainterAdapter extends Painter {
constructor() {
super()
const _defaultImplement = {
line() { console.log('default draw line') }
}
Object.keys(_defaultImplement).forEach((m) => {
this[m] = this[m] || _defaultImplement[m]
})
}
}
接下來就可以放心使用了:
const myPainter = new DefaultPainterAdapter()
myPainter.line()
myPainter.circle()
總結
適配器模式是比較簡單也比較常用的設計模式,它的作用是為API的提供者和使用者完成接口轉換弃甥,但是也增加了代碼量爽室。API的提供者與使用者應該盡量保持一致來避免這種額外的開銷。
與外觀模式的區(qū)別
適配器模式關注的是接口轉換淆攻,使得API的提供者和使用者不必關心對方的實現(xiàn)阔墩,體現(xiàn)的是解耦的思想;而外觀模式關注的是讓API保持統(tǒng)一的接口給API的使用者使用瓶珊,體現(xiàn)的是封裝的思想啸箫。