設計模式之適配器模式
來自專欄 web前端開發
模式動機
適配器模式的作用就是解決兩個軟體實體間介面不兼容情況.
通常情況下,使用者可以通過目標類的介面訪問它所提供的服務。開始時候沒有什麼問題, 但是一但後續別的介面(如第三方介面)有變動或者後續擴展需求, 此時使用原有介面已經不可以提供服務, 那麼我們就需要把現有介面轉化為使用者需要的介面.適配器模式就是用來完成這樣的轉化.
在適配器模式中可以定義一個包裝類,包裝不兼容介面的對象,這個包裝類指的就是適配器(Adapter),它所包裝的對象就是適配者(Adaptee),即被適配的類。
模式定義
適配器模式(Adapter Pattern) :將一個介面轉換成使用者希望的另一個介面,適配器模式使介面不兼容的那些類可以一起工作,其別名為包裝器(Wrapper)。適配器模式既可以作為類結構型模式,也可以作為對象結構型模式。
模式結構
適配器模式包含如下角色:
- Target:目標抽象類
- Adapter:適配器類
- Adaptee:適配者類
- Client:客戶類
現實世界舉例論證
現在世界中的適配器模式使用如: 港式插頭轉換器, 電源適配器, USB轉介面。
需求舉例代碼實現
我們需要完成一個集成多個第三方地圖sdk進行地圖渲染功能:
// 谷歌地圖,百度地圖sdk都有show方法進行調用。const googleMap = { show () { // 具體谷歌sdk的實現 console.log(開始使用谷歌地圖渲染) }};const baiduMap = { show () { // 具體百度sdk的實現 console.log(開始使用百度地圖渲染) }}// renderMap方法是提供給使用者來調用const renderMap = (map) => { if (map.show instanceof Function) { map.show(); }};renderMap(googleMap);renderMap(baiduMap);
這個時候產品需要我們集成高德地圖sdk,但是高德地圖渲染方法不是show方法,而是render方法.
這個時候我們不應該去改動之前的源代碼違反開閉原則. 而應該想到適配器模式.
// 谷歌地圖,百度地圖sdk都有show方法進行調用。const googleMap = { show () { // 具體谷歌sdk的實現 console.log(開始使用谷歌地圖渲染) }};const baiduMap = { show () { // 具體百度sdk的實現 console.log(開始使用百度地圖渲染) }}const gaodeMap = { render () { // 具體高德sdk的實現 console.log(開始使用高德地圖渲染) }}// 適配器const gaodeMapAdapater = { show () { return gaodeMap.render(); }}// renderMap方法是提供給使用者來調用const renderMap = (map) => { if (map.show instanceof Function) { map.show(); }};renderMap(googleMap);renderMap(baiduMap);renderMap(gaodeMapAdapater);
另外一個例子也是我們常見的場景---數據格式變更, 這個我在開發中經常遇到:
// 這是我們之前上傳資源, 後台返回給我們的文件信息.const responseUploadFile = { startTime: , file: { size: 100kb, type: text, url: , name: , ... }, id: }// 如果某天后台突然說因為某些原因後續上傳文件返回格式有變動了。如下const changeResUploadFile = { size: 100kb, type: text, url: , name: , startTime: , id: }// 由於我們之前使用舊格式數據做了很多業務邏輯,這個時候不能其改動,容易導致bug而且需求進行回歸測試.// 採用適配器模式const responseUploadFileAdapter = (uploadFile) => { // 在這裡對新的數據進行拼接轉化}
模式分析
優點:
- 將目標類和適配者類解耦,通過引入一個適配器類來重用現有的適配者類,而無須修改原有代碼。
- 增加了類的透明性和復用性,將具體的實現封裝在適配者類中,對於客戶端類來說是透明的
- 靈活性和擴展性都非常好,通過使用配置文件,可以很方便地更換適配器,也可以在不修改原有代碼的基礎上增加新的適配器類,完全符合「開閉原則」。
適用環境
- 系統需要使用現有的類,而這些類的介面不符合系統的需要。
- 想要建立一個可以重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。
參考資料
1. 適配器模式 - Graphic Design Patterns
推薦閱讀: