JS设计模式---10.适配器模式

适配器模式的作用

适配器模式可用来在现有接口和不兼容的类之间进行适配,使用这种模式的对象又叫包装器。(个人理解其实就是用来做兼容的一种模式)

特点

适配器可以被添加到现有代码中以协调两个不同的接口。
从表面上看,适配器模式和门面模式很像,它们都是要对别的对象进行包装并改变其呈现的接口。但是它们的不同之处就在于如何改变接口。门面元素只是一个简化的接口,并没有额外的选择,而适配器则要把一个接口转换到另一个接口,他不会滤除某些能力,也不会简化接口。

方法兼容

假设你有一个具有 3 个字符串参数的函数,但客户系统拥有的却是一个包含三个字符串元素的对象,此时就可以用一个适配器来衔接二者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 假设你有一个对象 还有一个以三个字符串味参数的函数
var obj = {
string1:"foo",
string2:"bar",
string3:"baz"
}
function interfaceMethod(str1,str2,str3){
// ...
}
// 为了把obj作为参数传递给interfaceMethod 需要用到适配器
function clientToInterfaceAdapter(o){
interfaceMethod(o.string1,o.string2,o.string3)
}
// 现在就可以把整个对象传递给这个函数
clientToInterfaceAdapter(obj)

吐槽一下,个人觉得,这种简单的完全没啥子必要。。。直接 interfaceMethod(obj.string1,obj.string2,obj.string3)又快又好。。可能书上是为了通熟易懂吧。

适配原有实现

在某些情况下,从客户一方对代码进行修改是不可能的。因此我们会避免创建 API。如果现有接口发生了改变,那么客户代码也必须进行相应的修改才能使用这个接口,否则整个应用系统就会有失灵的危险。在引入新接口之后,一般来说最好向客户方提供一些可为其实现新接口的适配器。

适配两个库

适配 Prototype 库的\$函数到 YUI 的 get 方法的转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Prototype $ function
function $(){
var elements = new Array();
for(vari=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 get method
YAHOO.util.Dom.get = function(el){
if(YAHOO.lang.isString(el)){
return document.getElementById(el);
}
if(YAHOO.lang.isArray(el)){
var c = [];
for(var i=0;i<el.length;i++){
c[c.length] = YAHOO.util.get(el[i])
}
return c;
}
if(el) return el;
return null
}

二者的区别在于:get 具有一个参数,这个参数可以是一个 HTML 元素 字符串或者由字符串或 HTML 元素组成的数组,而\$函数并没有正式列出参数,而是由客户任意传入任意数目的参数,不管是字符串还是 HTML 元素都行
如果需要从使用 Prototype 的\$函数改为使用 YUI 的 get 方法(或者相反),那么这个适配器需要这样写

1
2
3
4
5
6
7
8
9
10
function PrototypeToYUIAdapter(){
return YAHOO.util.Dom.get(arguments)
}
function YUIToPrototypeAdapter(el){
return $.apply(window,el intanceof Array ? el : [el])
}
// 对于从Prototype投奔YUI的人来说,只需要添加下面这行代码
$ = PrototypeToYUIAdapter
//同理 对于YUI改投Prototype的人来说
YAHOO.util.Dom.get = YUIToPrototypeAdapter