JS 適配器模式

1. 簡介

適配器模式(Adapter)是將一個類(對象)的接口(方法或屬性)轉化成客戶但願的另一個接口(方法或屬性),適配器模式使得本來因爲接口不兼容而不能一塊兒工做的那些類(對象)能夠一些工做。html

2. 實現

咱們來舉一個例子,鴨子(Dock)有飛(fly)和嘎嘎叫(quack)的行爲,而火雞雖然也有飛(fly)的行爲,可是其叫聲是咯咯的(gobble)。若是你非要火雞也要實現嘎嘎叫(quack)這個動做,那咱們能夠複用鴨子的quack方法,可是具體的叫還應該是咯咯的,此時,咱們就能夠建立一個火雞的適配器,以便讓火雞也支持quack方法,其內部仍是要調用gobble。前端

OK,咱們開始一步一步實現,首先要先定義鴨子和火雞的抽象行爲,也就是各自的方法函數:編程

// 鴨子抽象類
var Duck = function(){

};
Duck.prototype.fly = function(){
    throw new Error("該方法必須被重寫!");
};
Duck.prototype.quack = function(){
    throw new Error("該方法必須被重寫!");
}

// 火雞抽象類
var Turkey = function(){

};
Turkey.prototype.fly = function(){
    throw new Error(" 該方法必須被重寫 !");
};
Turkey.prototype.gobble = function(){
    throw new Error(" 該方法必須被重寫 !");
};

而後再定義具體的鴨子和火雞的構造函數,分別爲:segmentfault

//鴨子
var MallardDuck = function () {
    Duck.apply(this);
};
MallardDuck.prototype = new Duck(); //原型是Duck
MallardDuck.prototype.fly = function () {
    console.log("能夠飛翔很長的距離!");
};
MallardDuck.prototype.quack = function () {
    console.log("嘎嘎!嘎嘎!");
};

//火雞
var WildTurkey = function () {
    Turkey.apply(this);
};
WildTurkey.prototype = new Turkey(); //原型是Turkey
WildTurkey.prototype.fly = function () {
    console.log("飛翔的距離貌似有點短!");
};
WildTurkey.prototype.gobble = function () {
    console.log("咯咯!咯咯!");
};

爲了讓火雞也支持quack方法,咱們建立了一個新的火雞適配器TurkeyAdapter:後端

var TurkeyAdapter = function(oTurkey){
    Duck.apply(this);
    this.oTurkey = oTurkey;
};
TurkeyAdapter.prototype = new Duck();
TurkeyAdapter.prototype.quack = function(){
    this.oTurkey.gobble();
};
TurkeyAdapter.prototype.fly = function(){
    var nFly = 0;
    var nLenFly = 5;
    for(; nFly < nLenFly;){
        this.oTurkey.fly();
        nFly = nFly + 1;
    }
};

該構造函數接受一個火雞的實例對象,而後使用Duck進行apply,其適配器原型是Duck,而後要從新修改其原型的quack方法,以便內部調用oTurkey.gobble()方法。其fly方法也作了一些改變,讓火雞連續飛5次(內部也是調用自身的oTurkey.fly()方法)。設計模式

調用方法,就很明瞭了,測試一下即可以知道結果了:數組

var oMallardDuck = new MallardDuck();
var oWildTurkey = new WildTurkey();
var oTurkeyAdapter = new TurkeyAdapter(oWildTurkey);

//原有的鴨子行爲
oMallardDuck.fly();
oMallardDuck.quack();

//原有的火雞行爲
oWildTurkey.fly();
oWildTurkey.gobble();

//適配器火雞的行爲(火雞調用鴨子的方法名稱)
oTurkeyAdapter.fly();
oTurkeyAdapter.quack();

3. 其它應用

適配器模式也常常用於平常的數據處理上,好比把一個有序的數組轉化成咱們須要的對象格式:緩存

const arr = ['Javascript', 'book', '前端編程語言', '8月1日']
function arr2objAdapter(arr) {    // 轉化成咱們須要的數據結構
  return {
    name: arr[0],
    type: arr[1],
    title: arr[2],
    time: arr[3]
  }
}

const adapterData = arr2objAdapter(arr)

在先後端的數據傳遞的時候會常用到適配器模式,若是後端的數據常常變化,好比在某些網站拉取的數據,後端有時沒法控制數據的格式,因此在使用數據前最好對數據進行適配成咱們可用的數據格式再使用。微信

4. 總結

那合適使用適配器模式好呢?若是有如下狀況出現時,建議使用:數據結構

  1. 使用一個已經存在的對象,但其方法或屬性接口不符合你的要求;
  2. 你想建立一個可複用的對象,該對象能夠與其它不相關的對象或不可見對象(即接口方法或屬性不兼容的對象)協同工做;
  3. 想使用已經存在的對象,可是不能對每個都進行原型繼承以匹配它的接口。對象適配器能夠適配它的父對象接口方法或屬性。

另外,適配器模式和其它幾個模式可能容易讓人迷惑,這裏說一下大概的區別:

  1. 適配器和橋接模式雖然相似,但橋接的出發點不一樣,橋接的目的是將接口部分和實現部分分離,從而對他們能夠更爲容易也相對獨立的加以改變。而適配器則意味着改變一個已有對象的接口。
  2. 裝飾者模式加強了其它對象的功能而同時又不改變它的接口,所以它對應程序的透明性比適配器要好,其結果是裝飾者支持遞歸組合,而純粹使用適配器則是不可能的。
  3. 代理模式在不改變它的接口的條件下,爲另一個對象定義了一個代理。

本文是系列文章,能夠相互參考印證,共同進步~

  1. JS 抽象工廠模式
  2. JS 工廠模式
  3. JS 建造者模式
  4. JS 原型模式
  5. JS 單例模式
  6. JS 回調模式
  7. JS 外觀模式
  8. JS 適配器模式
  9. JS 利用高階函數實現函數緩存(備忘模式)
  10. JS 狀態模式
  11. JS 橋接模式
  12. JS 觀察者模式

網上的帖子大多深淺不一,甚至有些先後矛盾,在下的文章都是學習過程當中的總結,若是發現錯誤,歡迎留言指出~

參考:
《Javascript 設計模式》 - 張榮銘
設計模式之適配器模式

PS:歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~

另外能夠加入「前端下午茶交流羣」微信羣,長按識別下面二維碼便可加我好友,備註加羣,我拉你入羣~

相關文章
相關標籤/搜索