本回内容介绍
上一回,聊了代理模式,虚拟代理,图片懒加载,介一回,也比较容易,适配器模式(Adapter),用一个新的接口对现有类的接口进行包装,处理类与API的不匹配。使用这种模式的对象又叫做包装器(wrapper)。先看个简单的例子,先理解再深入,走你:
1.适配器模式
先定义一个接口(接收3个参数),再定义一个对象,如何衔接二者呢,如下:
// 定义一个接口方法,传3个参数
function interfaceMethod(a1,a2,a3){
// 随便写个弹出框
alert(a1+a2+a3+'');
}
// 定义一个对象
var o = {
s1:'飞狐就是帅',
s2:',撸壕,',
s3:'大卫'
}
// 适配器函数,把传递的对象参数转换为interfaceMethod函数需要的形式
function adapter(o){
interfaceMethod(o.s1,o.s2,o.s3);
}
adapter(o); //飞狐就是帅,撸壕,大卫
这是模拟JS设计模式书上例子,适配器的作用主要是对现有的接口进行包装,从而实现现有的接口和不兼容的类进行匹配。
这里很多盆友会疑惑适配器模式与门面模式的区别:
1,门面模式是为了简化一个接口,并不提供额外的选择;
2,适配器则要把一个接口转换为另一个接口,并不会滤除某些能力,也不会简化接口;
网上最多的一个例子,就是适配不同的库,如下:
2. 适配不同库
Prototype库的$函数到YUI的get方法的转换,网上最多的一个适配器模式的讲解,看例子:
<div id="fox1">飞狐</div><br/>
<div id="fox2">帅狐</div><br/>
<div id="fox3">主要看气质</div>
// 模拟Prototype,根据id获取DOM元素,不需要传递任何的形参,一个id写一个参数,多个id多个参数
function $(){
// 定义一个结果数组
var elements = [];
// 遍历传入参数
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;
}
// 模拟雅虎
var YAHOO = {};
// YUI中get只接受一个参数,字符串或数组
YAHOO.get = function(el){
// 判断是否为字符串
if(typeof el == 'string'){
return document.getElementById(el);
};
// 判断是否为数组
if(el instanceof Array){
var elements = [] ;
for(var i=0;i<el.length;i++){
elements[elements.length] = YAHOO.get(el[i]);
}
return elements;
}
// 如果都不是,直接返回
if(el){
return el;
}
// 否则返回null
return null;
}
// YUI适配器
YAHOO.get = YUIToPrototypeAdapter;
// 适配器函数
function YUIToPrototypeAdapter(){
// 对于YUI开发人员来说 永远传递一个参数
if(arguments.length == 1){
var el = arguments[0];
// 这里判断是否为数组,如果是直接返回,否则包装成数组返回,如:"a",包装后["a"]
return $.apply(window,el instanceof Array?el:[el]);
} else {
// 如果是多个参数的情况,这里只能用apply,不能用call
return $.apply(window,arguments);
}
}
// 测试数组的情况
var arr = YAHOO.get(['fox1','fox2','fox3']);
alert(arr);
// 测试多个参数的情况
var arr = YAHOO.get('fox1','fox2','fox3');
alert(arr);
这个例子在网上太多了,随便找了一个来改,目的在于模拟不同库直接的匹配,灵活的转换,解决与现有API提供的接口不兼容的冲突。
装逼时刻了,老片新看,推荐《重庆森林》,文艺范儿的调调~~
这一回聊适配器模式,就俩例子,内容不多,主要是理解。
下面的内容来一个图片预加载,跟上一回的懒加载凑一对兄弟篇。
JS图片预加载
图片预加载是web开发中一种应用相当广泛的技术,比如图片翻转显示等特效的时候,为了让图片在转换的时候不出现等待,先让图片下载到本地,再继续执行后续的操作:
//要加载的图片地址,这里可以随便在网上搜点儿图片测试
var imgs=[
"xxx.jpg",
"yyy.jpg",
"zzz.jpg"
];
var preload=function(imgs,callback){
// 判断传入的imgs是否为数组(typeof操作符检测数组的时候也是object),若不是数组则用[imgs]转为数组
var imgs=(typeof imgs!="object")? [imgs] : imgs;
// 定义一个图片数组
var img = [];
for(var i=0,len=imgs.length;i<len;i++){
// 为每一个图片对象赋值图片地址
img[i] = new Image();
img[i].src = imgs[i];
}
// 三目运算没什么好说的,len-1表示最后一个图片对象,加载完成执行回调函数,apply还记得吧,使作用域指向img
img[len-1].onload = callback?callback.apply(img):null;
}
// 测试
window.onload=function(){
preload(imgs,function(){
var _self = this;
_self.forEach(function(item){
alert(item.src);
})
});
}
这里只是简单的模拟,代码量少,应该可以很容易看懂,预加载减去了等待时间提高用户体验,很多web应用中广泛运用。
这一回,主要聊了适配器模式,图片预加载,主要还是理解~~
下一回,聊一聊桥接模式,顺便做一做计算题。
客观看完点个赞,推荐推荐呗,嘿嘿~~
注:此系飞狐原创,转载请注明出处
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。