适配器设计模式在JavaScript中非常有用,在处理跨浏览器兼容问题、整合多个第三方SDK的调用,都可以看到它的身影。

其实在日常开发中,很多时候会不经意间写出符合某种设计模式的代码,毕竟设计模式就是老前辈们总结提炼出来的一些能够帮助提升开发效率的一些模版,源于日常的开发中。

适配器其实在JavaScript中应该是比较常见的一种了。

在维基百科中,关于适配器模式的定义为:

在软件工程中,适配器模式是一种软件设计模式,允许从另一个接口使用现有类的接口。它通常用于使现有的类与其他类一起工作,而无需修改其源代码。

生活中的例子

在生活中最常见的就是电源插头的适配器了,世界各国的插座标准各不相同,如果需要根据各国的标准购买对应的电源插头那未免太过于浪费钱财,如果说自己带着插座,把人家墙敲碎,重新接线,也肯定是不现实的。

所以就会有插头的适配器,用来将某种插头转换成另一种插头,在插座和你的电源之间做中转的这个东西,就是适配器。

在代码中的体现

而转向到编程中,我个人是这样理解的:

将那些你不愿意看见的脏代码藏起来,你就可以说这是一个适配器

接入多个第三方SDK

举个日常开发中的例子,我们在做一个微信公众号开发,里边用到了微信的支付模块,经过长时间的联调,终于跑通了整个流程,正当你准备开心的打包上线代码的时候,得到了一个新需求:

我们需要接入支付宝公众号的SDK,也要有支付的流程

为了复用代码,我们可能会在脚本中写下这样的逻辑:

if (platform === 'wechat') {
wx.pay(config)
} else if (platform === 'alipay') {
alipay.pay(config)
} // 做一些后续的逻辑处理

但是一般来说,各厂的SDK所提供的接口调用方式都会多多少少有些区别, 虽说有些时候文档可能用的是同一份,致敬友商。

所以针对上述的代码可能是这样的:

// 并不是真实的参数配置,仅仅举例使用
const config = {
price: 10,
goodsId: 1
} // 还有可能返回值的处理方式也不相同
if (platform === 'wechat') {
config.appId = 'XXX'
config.secretKey = 'XXX'
wx.pay(config).then((err, data) => {
if (err) // error // success
})
} else if (platform === 'alipay') {
config.token = 'XXX'
alipay.pay(config, data => {
// success
}, err => {
// error
})
}

就目前来说,代码接口还算是清晰,只要我们写好注释,这也不是一个太糟糕的代码。

但是生活总是充满了意外,我们又接到了需求需要添加QQ的SDK、美团的SDK、小米的SDK,或者某些银行的SDK。

此时你的代码可能是这样的:

switch (platform) {
case 'wechat':
// 微信的处理逻辑
break
case 'QQ':
// QQ的处理逻辑
break
case 'alipay':
// 支付宝的处理逻辑
break
case 'meituan':
// 美团的处理逻辑
break
case 'xiaomi':
// 小米的处理逻辑
break
}

这已经不是一些注释能够弥补的问题了,这样的代码会变得越来越难维护,各种SDK千奇百怪的调用方式,如果其他人也要做类似的需求,还需要重新写一遍这样的代码,那肯定是很浪费资源的一件事儿。

所以为了保证我们业务逻辑的清晰,同时也为了避免后人重复的踩这个坑,我们会将它进行拆分出来作为一个公共的函数来存在:

找到其中某一个SDK的调用方式或者一个我们约定好的规则作为基准。

我们来告诉调用方,你要怎么怎么做,你能怎样获取返回数据,然后我们在函数内部进行这些各种肮脏的判断:

function pay ({
price,
goodsId
}) {
return new Promise((resolve, reject) => {
const config = {} switch (platform) {
case 'wechat':
// 微信的处理逻辑
config.price = price
config.goodsId = goodsId
config.appId = 'XXX'
config.secretKey = 'XXX'
wx.pay(config).then((err, data) => {
if (err) return reject(err) resolve(data)
})
break
case 'QQ':
// QQ的处理逻辑
config.price = price * 100
config.gid = goodsId
config.appId = 'XXX'
config.secretKey = 'XXX'
config.success = resolve
config.error = reject
qq.pay(config)
break
case 'alipay':
// 支付宝的处理逻辑
config.payment = price
config.id = goodsId
config.token = 'XXX'
alipay.pay(config, resolve, reject)
break
}
})
}

这样无论我们在什么环境下,只要我们的适配器支持,就可以按照我们约定好的通用规则进行调用,而具体执行的是什么SDK,则是适配器需要关心的事情:

// run anywhere
await pay({
price: 10,
goodsId: 1
})

对于SDK提供方,仅仅需要知道自己所需要的一些参数,然后按照自己的方式进行数据返回。

对于SDK调用房,仅仅需要我们约定好的通用的参数,以及按照约定的方式进行监听回调处理。

整合多个第三方SDK的任务就交由适配器来做,然后我们将适配器的代码压缩,混淆,放在一个看不见的角落里去,这样的代码逻辑就会变得很清晰了

适配器在JavaScript中的体现的更多相关文章

  1. javascript中的Function和Object

    写的很好,理解了很多,特此转发记录 转自:http://blog.csdn.net/tom_221x/archive/2010/02/22/5316675.aspx 在JavaScript中所有的对象 ...

  2. 详解Javascript中正则表达式的使用

    正则表达式用来处理字符串特别好用,在JavaScript中能用到正则表达式的地方有很多,本文对正则表达式基础知识和Javascript中正则表达式的使用做一个总结. 第一部分简单列举了正则表达式在Ja ...

  3. 【总结】浅谈JavaScript中的接口

    一.什么是接口 接口是面向对象JavaScript程序员的工具箱中最有用的工具之一.在设计模式中提出的可重用的面向对象设计的原则之一就是“针对接口编程而不是实现编程”,即我们所说的面向接口编程,这个概 ...

  4. Javascript中prototype属性详解

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不 ...

  5. 关于javascript中apply()和call()方法的区别

    如果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而怪异的感觉,因为意识上往往不可能的事偏偏就发生了,甚至觉得不可理喻.如果在学JavaScript这自由而变幻无穷的语 ...

  6. JavaScript中的arguments,callee,caller

    在提到上述的概念之前,首先想说说javascript中函数的隐含参数: arguments: arguments 该对象代表正在执行的函数和调用它的函数的参数. [function.]argument ...

  7. 理解JavaScript中的参数传递 - leetcode189. Rotate Array

    1.关于leetcode 这是第一篇关于leetcode的题解,就先扯点关于leetcode的话. 其实很早前就在博客园看到过leetcode一些题解,总以为跟一般OJ大同小异,直到最近点开了一篇博文 ...

  8. JavaScript中的类型转换(一)

    前言 JavaScript是一种非常灵活的弱类型的语言,它的灵活性的一方面体现在其繁杂多样的类型转换.比如当JavaScript期望使用一个布尔值的时候(比如if语句中)你可以提供任一类型的值,Jav ...

  9. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

随机推荐

  1. Codechef_JULY14

    感觉这套比赛题目比较容易,没有以前做过的某次codechef那么凶残.题目还是很有意思的,最好的是有中文翻译. CSUB:签到题,直接从左往右扫一遍即可,维护前面出现过多少个1. #include & ...

  2. BZOJ3162 独钓寒江雪(哈希+树形dp)

    数独立集显然是可以树形dp的,问题在于本质不同. 假设已经给树确立了一个根并且找到了所有等效(注意是等效而不是同构)子树,那么对转移稍加修改使用隔板法就行了. 关键在于找等效子树.首先将树的重心(若有 ...

  3. 函数防抖与函数节流 封装好的debounce和throttle函数

    /** * 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行 * * @param {function} func 传入函数,最后一个参数是额外增加的this对象,. ...

  4. ORA-01410: 无效的 ROWID

    视图查询单表是有这个东西的,但是视图的SQL涉及多表关联,就没这个rowid了,要么自己写个,要么不用这个ROWID做啥动作

  5. Tengine,轻量级Web服务器

    阿里妹导读:Tengine,轻量级Web服务器,基于Nginx进行开发,针对大访问量网站的需求,新增了很多高级功能和特性.比如,Tengine兼容Nginx的所有配置,并且增加了独立进程框架.页面优化 ...

  6. 【BZOJ4059】Non-boring sequences

    Solution 记序列为\(a\),计算出与\(a_i\)相等的前一个元素的位置\(pre_i\),以及后一个元素的位置\(nex_i\),显然,对于那些左端点处于\((pre_i,i]\)以及右端 ...

  7. hadoop进阶----hadoop经验(一)-----生产环境hadoop部署在超大内存服务器的虚拟机集群上vs几个内存较小的物理机

    生产环境 hadoop部署在超大内存服务器的虚拟机集群上 好 还是  几个内存较小的物理机上好? 虚拟机集群优点 虚拟化会带来一些其他方面的功能. 资源隔离.有些集群是专用的,比如给你三台设备只跑一个 ...

  8. 利用poi来向execl中写入对象

    附上jar包下载链接: 附上百度网盘下载连接: 链接:https://pan.baidu.com/s/1t_jXUq3CuhZo9j_UI4URAQ 密码:r2qi package com.wz.po ...

  9. windows 10 enterprise 企业版 mak激活密钥

    企业版用户请依次输入: slmgr /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43 slmgr /skms kms.xspace.in slmgr /ato

  10. 在eclipse中安装 Activiti Designer插件

    转: Activiti系列——如何在eclipse中安装 Activiti Designer插件 这两天在评估jbpm和Activiti,需要安装一个Activiti Designer插件试用一下. ...