本文详解JavaScript中的适配器模式,旨在解决两个软件实体接口不兼容的问题。通过地图渲染和数据格式转换两个实例,展示如何创建适配器将旧接口转换为新接口,无需修改原有代码即可实现协同工作,并对比了装饰者、代理及外观模式的区别。
适配器模式
该模式的核心价值在于解决两个软件实体间接口不兼容的问题。应用适配器后,原本因接口差异无法协同工作的两个实体得以共同运行。
适配器也被称为包装器(wrapper),属于相对简单的模式。开发中常遇到需调用模块或对象接口,却发现格式不符需求的情况。此时有两种解决路径:一是修改原接口实现,但若原模块复杂或源码经过压缩,修改往往不现实;二是创建适配器,将原接口转换为客户期望的接口,使客户仅与适配器交互。
适配器模式的应用
若现有接口能正常工作,则无需使用适配器。这是一种“亡羊补牢”的模式,通常不在设计初期使用,因为无法完全预见未来。若当前工作的接口未来不再适用于新系统,可通过适配器将旧接口包装为新接口,使其保持可用。例如,在JSON流行前,许多API返回XML格式数据,如今若需继续使用这些接口,可创建XML-JSON适配器。
以下实例有助于深入理解适配器模式。
当向 googleMap 和 baiduMap 发出“显示”请求时,googleMap 和 baiduMap 分别以各自方式在页面中展示地图:
const googleMap = {
show: function () {
console.log('开始渲染谷歌地图');
}
};
const baiduMap = {
show: function () {
console.log('开始渲染百度地图');
}
};
const renderMap = function (map) {
if (map.show instanceof Function) {
map.show();
}
};
renderMap(googleMap); // 输出:开始渲染谷歌地图
renderMap(baiduMap); // 输出:开始渲染百度地图 程序顺利运行的关键在于 googleMap 和 baiduMap 提供了一致的 show 方法。然而,第三方接口方法不受我们控制,若 baiduMap 提供的显示地图方法不叫 show 而叫 display 呢?
baiduMap 对象源自第三方,通常不应直接修改。此时可通过增加 baiduMapAdapter 来解决问题:
const googleMap = {
show: function () {
console.log('开始渲染谷歌地图');
}
};
const baiduMap = {
display: function () {
console.log('开始渲染百度地图');
}
};
const baiduMapAdapter = {
show: function () {
return baiduMap.display();
}
};
renderMap(googleMap); // 输出:开始渲染谷歌地图
renderMap(baiduMapAdapter); // 输出:开始渲染百度地图再看另一个例子。假设正在编写渲染广东省地图的页面。目前从第三方资源获取了广东省所有城市及其对应ID,并成功渲染到页面:
const getGuangdongCity = function () {
const guangdongCity = [{
name: 'shenzhen',
id: 11,
}, {
name: 'guangzhou',
id: 12,
}];
return guangdongCity;
};
const render = function (fn) {
console.log('开始渲染广东省地图');
document.write(JSON.stringify(fn()));
};
render(getGuangdongCity);利用这些数据完成了页面编写,并在线上稳定运行一段时间。后发现数据不可靠,缺少许多城市。于是找到其他数据资源,数据更全面,但数据结构与当前项目不一致。新数据结构如下:
const guangdongCity = {
shenzhen: 11,
guangzhou: 12,
zhuhai: 13
};
除大改前端渲染代码外,更轻便的方式是新增一个数据格式转换适配器:
const getGuangdongCity = function () {
const guangdongCity = [{
name: 'shenzhen',
id: 11,
}, {
name: 'guangzhou',
id: 12,
}];
return guangdongCity;
};
const render = function (fn) {
console.log('开始渲染广东省地图');
document.write(JSON.stringify(fn()));
};
const addressAdapter = function (oldAddressfn) {
const address = {},
oldAddress = oldAddressfn();
for (let i = 0; i < oldAddress.length; i++) {
address[oldAddress[i].name] = c.id;
}
return function () {
return address;
}
};
render(addressAdapter(getGuangdongCity));接下来,需将代码中调用 getGuangdongCity 的地方,替换为经过 addressAdapter 适配器转换后的新函数。
小结
适配器模式是一对相对简单的模式。部分模式如装饰者模式、代理模式和外观模式,其结构与适配器模式非常相似。这些均属于“包装模式”,由一个对象包装另一个对象。区分它们的关键在于模式意图。
- 适配器模式主要用于解决两个已有接口间不匹配的问题,不考虑接口实现方式及未来演化。它无需改变已有接口,即可使它们协同作用。
- 装饰者模式和代理模式也不改变原有对象接口,但装饰者模式旨在为对象增加功能,常形成长链;适配器模式通常只包装一次。代理模式用于控制对象访问,通常也只包装一次。
- 外观模式作用与适配器较相似,有人视其为对象组的适配器,但外观模式最显著特点是定义了新接口。
到此这篇关于JavaScript适配器模式的应用详解的文章就介绍到这了,更多相关JS适配器模式内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!