定义
适配器模式是解决两个类之间的方法不兼容的问题。使用适配器模式之后,原本由于方法不兼容而不能工作的两个类可以一起工作。
适配器模式是一个相对简单的模式。在程序开发中有许多这样的场景:当我们试图调用模块或者对象的某个方法时,却发现这个方法的格式并不符合目前的需求。
这时候有两种解决办法,第一种是修改原来的方法实现,但如果原来的模块很复杂,或者我们拿到的模块是一段别人编写的经过压缩的代码,修改原方法就显得不太现实了。第二种办法是创建一个适配器,将原方法转换为客户希望的另一个方法,客户只需要和适配器打交道。
理解
用一个生活中的例子来理解,比如笔记本的电池支持的电压是 20V,在日常生活中的交流电压一般是 220V。除了 220V 交流电压,日本和韩国的交流电压大多是 100V,而英国和澳大利亚的是 240V。笔记本电脑的电源适配器就承担了转换电压的作用,电源适配器使笔记本电脑在 100V~240V 的电压之内都能正常工作,这也是它为什么被称为电源适配器的原因。
应用
如果现有的方法已经能够正常工作,那我们就永远不会用上适配器模式。适配器模式是一种“亡羊补牢”的模式,没有人会在程序的设计之初就使用它。因为没有人可以完全预料到未来的事情,也许现在好好工作的方法,未来的某天却不再适用于新系统,那么我们可以用适配器模式把旧方法包装成一个新的方法,使它继续保持生命力。
假如有一个需求,切换tab时展示不同的地图
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); // 输出:开始渲染百度地图
以上baiduMapAdapter
就是baiduMap
的适配器。
与装饰者模式、代理模式和外观模式的区别
-
适配器模式主要用来解决两个已有方法之间不匹配的问题,它不考虑这些方法是怎样实现的,也不考虑它们将来可能会如何演化。适配器模式不需要改变已有的方法,就能够使它们协同作用。
-
装饰者模式和代理模式也不会改变原有对象的方法,但装饰者模式的作用是为了给对象增加功能。装饰者模式常常形成一条长的装饰链,而适配器模式通常只包装一次。代理模式是为了控制对对象的访问,通常也只包装一次。
-
外观模式的作用倒是和适配器比较相似,有人把外观模式看成一组对象的适配器,但外观模式最显著的特点是定义了一个新的方法。