什么是适配器模式
我们来看一张图片:
从iphone7 开始,苹果取消了3.5mm耳机接口。那老的耳机就不能在新的手机上使用了,于是就有了Lightning转3.5毫米耳机转接口。这就是我们生活中一个非常典型的适配器模式的应用。
回到我们的程序语言中,当我(耳机)需要调用某个接口(连接iphone)时,发现接口发生了改动(3.5mm口改成了Lightning口),我们又不想修改我们的调用代码(老耳机还需要连接iphone5s的3.5mm接口)。于是我们就绪需要一个Adapter(转接口)来实现我们的功能。
代码示例
// iphone5sfunction iphone5s () {// 插入耳机方法this.insert = function (interfaceType) {if (interfaceType == '3.5mm') {console.log('playing music in 5')} else {throw 'interface no match'}}}// iphone7function iphone7 () {// 插入耳机方法this.insert = function (interfaceType) {if (interfaceType == 'Lightning') {console.log('playing music in 7')} else {throw 'interface no match'}}}// 老的3.5mm的耳机function earphoneOld () {var type = '3.5mm'this.insert = function (phoneInstance) {phoneInstance.insert(type)}}// 转接口1function Adapter1 (earphone) {var convertType = function () {return 'Lightning'}var insert = function (phoneInstance) {phoneInstance.insert(convertType())}return {insert: insert}}var IPHONE5 = new iphone5()var IPHONE7 = new iphone7()var EARPHONEOLD = new earphoneOld()// 老耳机 + iphone5EARPHONEOLD.insert(IPHONE5) // 'playing music in 5'EARPHONEOLD.insert(IPHONE7) // Error 'interface no match'// 添加适配器Adapter1(EARPHONEOLD).insert(IPHONE7)// 'playing music in 7'
第三方库的适配场景
通常我们在业务代码中使用ajax请求库的时候会在调用端做一套封装
// 通用的Ajax调用方法var Ajax = function (options) {// 具体实现}// 使用AjaxAjax({url: 'xxx',type: 'GET',header: {},callback: function (data) {}})
这么做一方面可以在通用Ajax方法中对错误和异常做一些通用处理,另一方面,能勾通过适配器的方式灵活对第三方库进行替换,方便我们做一些潜在的升级工作。
var Ajax = function (o) {// jquery ajax adaptervar option = Object.assign({}, {url: o.url,type: o.type,success: o.callback,... // other options})// 使用jquery的ajax$.ajax(option)}// 如果需要移除业务的jquery依赖var Ajax = function (o) {// axios ajax adaptervar option = Object.assign({}, {... // adpater options})// 使用jquery的ajaxaxios(option)}
如此,当需要改动第三方库时,我们只要修改中间层适配器即可,而无需在每一行业务代码调用处进行修复。
其他应用场景
- 数据格式转换适配
-
优点
将目标和调用方解耦,通过引入一个适配器来重用现有的调用方,无需修改原有结构。
- 灵活性、扩展性好,可以通过使用配置文件,很方便的更换适配器,
可以在不修改原有代码的基础上,增加新的适配器,完全复合开闭原则
缺点
一次最多只能适配一个适配者类,不能同时适配多个适配者。
