什么是适配器模式
把一个类的接口变换成客户端所期待的另一种接口,通常用来解决不兼容的问题。
举个🌰:
喜欢听歌的你有一副音质很棒的3.5mm圆形插口🎧,但是你的手机很旧了,换了个新的,你发现这个新手机并没有圆形耳机插孔,只有一个 type-C 接口,无法使用原来的🎧听歌,聪明的你到某宝搜了一下耳机适配器:
然后你买了,愉快的听起了歌。实际场景
在以前的项目中,发请求是这么封装的:
js
function Request(type, url, data, success, failed) {
// 创建ajax对象
var xhr = null;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
// 此处省略一系列的业务逻辑细节
var type = type.toUpperCase();
// 识别请求类型
if (type == 'GET') {
xhr.open('GET', url + data ? '?' + Object.keys(data).map(key => `${key}=${data[key]}`).join('&') : '', true);
// 发送get请求
xhr.send();
} else if (type == 'POST') {
xhr.open('POST', url, true);
// 如果需要像 html 表单那样 POST 数据,使用 setRequestHeader() 来添加 http 头。
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 发送post请求
xhr.send(data);
}
// 处理返回数据
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
success(xhr.responseText);
} else {
if (failed) {
failed(xhr.status);
}
}
}
}
}
但是现在比较好用的方案是axios,它是这么使用的:
js
// get
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// post
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
如果现在需要升级,使用 axios 来请求,那就可以使用适配器模式来实现:
js
function requestAdapter(type, url, data, success, failed) {
const type = type.toLowerCase()
if (axios[type]) {
axios[type](url, {
params: data,
data
}).then(res => {
success && success(res)
}).catch(err => {
failed && failed(err)
})
}
}
何时用
- 系统需要使用现有的类,而此类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
- 通过接口转换,将一个类插入另一个类系中。
- 适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。
优点
- 可以让任何两个没有关联的类一起运行。
- 提高了类的复用。
- 增加了类的透明度。
- 灵活性好。
缺点
过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。