文:阿蜜果/2011-11-10
转载请注明出处
看一年前在当当网所买,却还崭新的那本《JavaScript设计模式》(Rose Harmes、Dustin Diaz 著,谢廷晟 译,人民邮电出版社出版),作者将GoF合著的《Design Patterns》一书中若干设计模式在JavaScript中的应用给了详尽的解说,不失为一本好书。
我比较喜欢的设计模式有工厂模式、适配器模式、组合模式和观察者模式等,本文总结书中关于适配器模式的讲解,希望该模式能为读者在JavaScript开发中所用。
1、 什么是适配器模式?
在计算机编程中,适配器模式将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。如果现有的接口能很好地满足需要,那就可能没有必要使用适配器。
从表面上看,适配器模式很像门面模式。它们都要对别的对象进行包装并改变其呈现的接口。两者的区别在于它们如何改变接口。门面元素展现的是一个简化的接口,它并不提供额外的选择,而且有时为了方便完成任务它还要做出某些假定。而适配器则要把一个叫接口转换成另外一个接口,它并不会滤除某些能力,也不会简化接口。
2、 适配器模式的应用场合
下面举几个适合使用适配器模式的实例:
(1) 参数类型不一致: 假设有这样一个对象,定义如下:
string1: 'foo',
string2: 'bar',
string3: 'baz'
} ;
另外有一个以三个字符串为参数的函数:
}
为了将cientObject作为参数传递给interfaceMethod方法,可使用适配器模式解决:
interfaceMethod(o.string1, o.string2, o.string3);
}
现在可以将clientObject对象作为参数传给clientToIntefaceAdapter方法:
使用适配器模式节解决了参数类型有些许不一致造成的问题。
(2)PS2-to-USB适配器:我比较喜欢这个关于适配器的例子,很好理解适配器的作用。 以PC硬件为例,PS2插口是连接鼠标和键盘的标准接口。多年以来几乎所有PC都带有这种接口,鼠标和键盘的设计人员因此就有了一个固定的设计目标。后来硬件工程师发明了可以完全替代PS2接口的技术,这种设计改用USB系统来支持键盘、鼠标和其他外设。
但是问题出现了,对于设计主板的工程师来说,消费者有没有USB键盘都无所谓,他们决定不再支持PS2插口,以便降低成本和节省空间。但是键盘和鼠标的设计者要想卖掉以前针对PS2接口成产的成千上万的键盘和鼠标,需要有适配器的支持才行,PS2-to-USB应运而生。
3、 在JavaScript中使用适配器模式
现在可供选择的库非常多,看看哪套工具最适合自己的需要,以及它们对自己的开发会带来什么影响。此外还要考虑开发人员的编程风格、实现难易程度和兼容性等等问题。即使以前选定了库,但可能出于性能、安全或设计等方面的考虑,可能会更换所用的库。
那要怎么样才能实现两个库之间的平滑过渡呢?此时可以使用适配器模式从一套API过渡到另一套API。例如在下面的实例中实现的是从Prototype库的$函数到YUI(Yahoo!User Interface)的get方法的转换。这两个函数功能相似,但接口方面有些区别。首先看看Prototype的$函数:
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
if (arguments.length == 1) {
return element;
}
elements.push(element);
}
return elements;
}
YUI(Yahoo!User Interface)的get方法的代码如下:
if (YAHOO.lang.isString(el)) {
return document.getElementById(el);
}
if (YAHOO.lang.isArray(el)) {
var c = [];
for (var i = 0, len = el.length; i < len; ++i) {
c[c.length] = YAHOO.util.Dom.get(el[i]);
}
return c;
}
if (el) {
return el;
}
return null;
} ;
两者的区别:get具有一个参数,这个参数可以是一个HTML元素、字符串或由字符串或HTML元素组成的数组。而$函数没有正式列出参数,而是允许用户传入任意数目的参数,可以是字符串或HTML元素。
如果想要Prototype的$函数改为使用YUI的get方法,可使用如下这个适配器:
return YAHOO.util.Dom.get(arguments);
}
只要添加如下代码后,在Prototype代码库被替换YAHOO后,$方法可以照用:
将YAHOO的get方法适配成Prototype的$方法的适配器如下:
return $.apply(window, el instanceof Array ? el : [el]);
}
只要添加如下代码后,在YAHOO代码库被替换Prototype后,get方法可以照用:
4、 适配器模式的优缺点
适配器最大的优点是可以避免大规模的改写现有客户代码。
如果现有API还未定形,或新接口还未定形,此时并不适合使用适配器模式。
5、 参考文档
(1)《JavaScript设计模式》 Ross Harmes,Dustin Dial著,谢廷晟 译,人民邮电出版社出版
(2)《适配器模式_百度百科》:
http://baike.baidu.com/view/3371585.htm