适配器模式的作用是解决两个软件实体间的接口不兼容问题。使用适配器模式之后,原本由于接口不兼容而不能工作的两个软件实体可以一起工作。
适配器模式的应用
适配模式是一种“亡羊补牢”的模式,没有人会在程序的设计之初就使用它,因为没有人可以完全预料到未来的事情,也许现在好好工作的接口未来就不再适用于新系统,那么我们可以使用适配器模式把旧的接口包装成新的接口,使他继续保持生命力。
比如在json数据流行之前,很多cgi返回的都是XML格式的数据,如果今天仍然想用这些接口,显然我们可以创造一个XML-JSON适配器。
比如有一段代码,我们向googleMap和baiduMap都发出显示请求时,他们分别以各自的方式在页面中展现了地图:
var googleMap = {
show: function() {
console.log(‘开始渲染谷歌地图’);
}
};
var baiduMap = {
show: function() {
console.log(‘开始渲染百度地图’);
}
};
var renderMap = function(map) {
if (map.show.instanceof Function) {
map.show();
}
};
renderMap(googleMap); //开始渲染谷歌地图
renderMap(baiduMap); //开始渲染百度地图
这个程序能运行的关键之处在于googleMap
和baiduMap
提供了一致的show方法,但是第三方接口并不在我们的控制范围内,加入baiduMap
提供的显示地图的方法不叫show
,而叫display
呢?
此时我们可以通过增加baiduMapAdapter
来解决问题:
var googleMap = {
show: function() {
console.log(‘开始渲染谷歌地图’);
}
};
var baiduMap = {
display: function() {
console.log(‘开始渲染百度地图’);
}
};
var baiduAdapter = {
show: function() {
return baiduMap.display();
}
};
var renderMap = function(map) {
if (map.show.instanceof Function) {
map.show();
}
};
renderMap(googleMap); //开始渲染谷歌地图
renderMap(baiduAdapter); //开始渲染百度地图
小结
适配器模式是一对相对简单的模式,但是有一些模式跟适配器模式的结构非常相似,比如装饰者模式,代理模式和外观模式,这几种都属于“包装模式”,都是一个对象来包装另一个对象。我们现在就来做一些区分:
-
适配器模式主要用来解决两个已有接口之间的不匹配问题,它不需要考虑这些接口是怎样实现的,也不考虑它们讲来可能会如何演化。适配器模式不需要改变已有接口,就能够实现它们的协同作用。
-
装饰者模式和代理模式也不会改变原有对象的接口,但装饰者模式的作用是为了给对象增加功能。装饰者模式常常形成一条长的装饰链,而适配器模式通常只包装一次。代理模式是为了控制对象的访问,通常也只包装一次。
-
外观模式的作用和适配器比较像是,有人把外观模式看成一组对象的适配器,但外观模式最显著的特点是定义了一个新的接口。