适配器模式(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:欢迎你们关注个人公众号【前端下午茶】,一块儿加油吧~
另外能够加入「前端下午茶交流群」微信群,长按识别下面二维码便可加我好友,备注加群,我拉你入群~