适配器在JavaScript中的体现
适配器设计模式在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中的体现的更多相关文章
- javascript中的Function和Object
写的很好,理解了很多,特此转发记录 转自:http://blog.csdn.net/tom_221x/archive/2010/02/22/5316675.aspx 在JavaScript中所有的对象 ...
- 详解Javascript中正则表达式的使用
正则表达式用来处理字符串特别好用,在JavaScript中能用到正则表达式的地方有很多,本文对正则表达式基础知识和Javascript中正则表达式的使用做一个总结. 第一部分简单列举了正则表达式在Ja ...
- 【总结】浅谈JavaScript中的接口
一.什么是接口 接口是面向对象JavaScript程序员的工具箱中最有用的工具之一.在设计模式中提出的可重用的面向对象设计的原则之一就是“针对接口编程而不是实现编程”,即我们所说的面向接口编程,这个概 ...
- Javascript中prototype属性详解
在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不 ...
- 关于javascript中apply()和call()方法的区别
如果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而怪异的感觉,因为意识上往往不可能的事偏偏就发生了,甚至觉得不可理喻.如果在学JavaScript这自由而变幻无穷的语 ...
- JavaScript中的arguments,callee,caller
在提到上述的概念之前,首先想说说javascript中函数的隐含参数: arguments: arguments 该对象代表正在执行的函数和调用它的函数的参数. [function.]argument ...
- 理解JavaScript中的参数传递 - leetcode189. Rotate Array
1.关于leetcode 这是第一篇关于leetcode的题解,就先扯点关于leetcode的话. 其实很早前就在博客园看到过leetcode一些题解,总以为跟一般OJ大同小异,直到最近点开了一篇博文 ...
- JavaScript中的类型转换(一)
前言 JavaScript是一种非常灵活的弱类型的语言,它的灵活性的一方面体现在其繁杂多样的类型转换.比如当JavaScript期望使用一个布尔值的时候(比如if语句中)你可以提供任一类型的值,Jav ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
随机推荐
- SpringBoot(五)_表单验证
SpringBoot(五)_表单验证 参数校验在我们日常开发中非常常见,最基本的校验有判断属性是否为空.长度是否符合要求等,在传统的开发模式中需要写一堆的 if else 来处理这些逻辑,很繁琐,效率 ...
- IE显示对象不支持此属性或方法 的解决方法
用C# 编写的ActiveX控件, 调试时,在世界之窗浏览器里能正确显示,但是不能和JS交互,也没有传说中的错误信息框出现,查了很多文档,后来想问题是不是出在浏览器上,换在IE8里调试,点击交互按钮, ...
- 使用SQLyog连接MySQL数据库
[学习笔记]使用SQLyog连接MySQL数据库 一.使用SQLyog创建数据库用来管理学生信息 复制代码 1 #创建数据库student 2 DROP DATABASE IF EXISTS Mys ...
- kafka-connect-hive Sink插件入门指南
kafka-connect-hive是基于kafka-connect平台实现的hive数据读取和写入插件,主要由source.sink两部分组成,source部分完成hive表数据的读取任务,kafk ...
- 51nod 1785 数据流中的算法 | STL的应用
51nod 1785 数据流中的算法 题面 动态求平均数.方差.中位数. 题解 这道题的坑: 平均数在答案中是向下取整输出并在后面添加".00" 方差:平方的平均数减去平均数的平方 ...
- 使用IPMI控制/监控Linux服务器
1 IPMI简述 IPMI提供了很多丰富功能,我使用的功能,说得大白话一点,就是: 1.获取本设备的硬件信息:包括CPU和主板的温度.电压.风扇转速. 2.在设备A上,通过命令,控制远程设 ...
- 东北育才 NOIP模拟赛第1场
终于400了.这套题很鬼畜.两道贪心. GRACE sort过后,不能直接统计,本人毫无多想,相同的直接放在一起.结果太多人AC. SUM sigma+异或和(可使用前缀和处理),本人毫无考虑乱MOD ...
- 3:JavaBean,EJB,POJO
JavaBeanJavaBean是公共Java类,但是为了编辑工具识别,需要满足至少三个条件: 有一个public默认构造器(例如无参构造器,) 属性使用public 的get,set方法访问,也就是 ...
- codeforces.com/contest/251/problem/C
C. Number Transformation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- Hadoop生态圈-Hbase的协处理器(coprocessor)应用
Hadoop生态圈-Hbase的协处理器(coprocessor)应用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.