什么是适配器模式?
举一个我工作中的例子:某一天,我觉得公司自带的键盘不好用,我想用自己的机械键盘。正当我从家里把键盘一路扛到公司时,发现!公司电脑USB是被禁用的(说是防泄密...)!
我心想:“难道要新买一把圆头接口的机械键盘了?”。其实大可不必,一个USB转圆头的适配器就可以帮我搞定这个兼容问题。此时这个适配器,就可以理解为设计模式中的适配器
应用场景
背景
某一天,我在浏览技术文章时,发现了一个fetch方法,可以用来发送请求。而且还返回promise。
我心想,这不错啊,用起来可比ajax简洁多了。说时迟那时快,立刻开始封装~
// httpUtils.js
class HttpUtils {
static doGet(url) {
return new Promise((resolve, reject) => {
fetch(url).then(res => res.json()).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
static doPost(url, data) {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
// 将object类型的数据格式化为合法的body参数
body: this.changeData(data)
}).then(res => res.json()).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
static changeData(obj) {
var prop,
str = ''
var i = 0
for (prop in obj) {
if (!prop) {
return
}
if (i == 0) {
str += prop + '=' + obj[prop]
} else {
str += '&' + prop + '=' + obj[prop]
}
i++
}
return str
}
}
// 使用时:
const url = 'https://api.github.com/users/ygunoil'
const params = { name: 'xxx' }
const postResponse = HttpUtils.doPost(url, params)
const getResponse = HttpUtils.doGet(url)
封装完后,开心了没几天,组长发现我封装的方法说到:“小伙子不错,我们现在把系统里所有的方法统一一下,就用你这个HttpUtils方法来发送请求吧。”我人懵了,因为我知道,之前的请求封装的是XMLHttpRequest,关键是,连入参和调用方式都不一样。
// 老旧的请求发送方式
/*
url,请求路径
method,请求方法
params,请求参数
success:请求成功的回调
fail:请求失败的回调
*/
const getResponse = ajax('tom/a','GET',{name:'xxx'},(res)=>{},(err)=>{})
解决方案
难道我要一个个改吗?既要更改传参,又要更改调用方式???这也太麻烦了。好在我知道适配器模式!开干!
// 更改旧的ajax方法
function ajax(url,method,params,success,fail){
// 适配器函数登场
AjaxAdapter(url,method,params,success,fail)
}
async AjaxAdapter(url,method,params,success,fail){
let result = null
if(method.toLowerCase() === 'get'){
result = await HttpUtils.doGet(url)
}else{
result = await HttpUtils.doPost(url,params)
}
if(result && result.code === 200){
// 假设成功的code为200
success(result)
}else{
fail(result)
}
}
如此一来,我只需要写一个适配器函数AjaxAdapter,就可以来保持新旧函数方法的统一了~