適配器模式(Adapter)是將一個類(對象)的接口(方法或屬性)轉化成客戶但願的另一個接口(方法或屬性),適配器模式使得本來因爲接口不兼容而不能一塊兒工做的那些類(對象)能夠一些工做。html
咱們來舉一個例子,鴨子(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();
適配器模式也常常用於平常的數據處理上,好比把一個有序的數組轉化成咱們須要的對象格式:緩存
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)
在先後端的數據傳遞的時候會常用到適配器模式,若是後端的數據常常變化,好比在某些網站拉取的數據,後端有時沒法控制數據的格式,因此在使用數據前最好對數據進行適配成咱們可用的數據格式再使用。微信
那合適使用適配器模式好呢?若是有如下狀況出現時,建議使用:數據結構
另外,適配器模式和其它幾個模式可能容易讓人迷惑,這裏說一下大概的區別:
本文是系列文章,能夠相互參考印證,共同進步~
網上的帖子大多深淺不一,甚至有些先後矛盾,在下的文章都是學習過程當中的總結,若是發現錯誤,歡迎留言指出~
參考:
《Javascript 設計模式》 - 張榮銘
設計模式之適配器模式
PS:歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~
另外能夠加入「前端下午茶交流羣」微信羣,長按識別下面二維碼便可加我好友,備註加羣,我拉你入羣~