JS设计模式——代理模式

  代理模式是指为一个对象提供一个代用品或者占位符,以便控制对它的访问。

代理模块可以对请求做一定的处理之后再传递给业务模块,这样就可以把一些与核心业务无关的东西剥离出来,保持业务逻辑的“纯净”。更具体的,代理按作用可以分为两类:

  • 保护代理:用于过滤请求,控制对业务模块的访问权限,保护业务模块;
  • 虚拟代理:把一些开销比较大的对象,延迟到真正需要它的时候才去创建。

一、虚拟代理实现图片预加载

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
29
/*业务逻辑模块,负责创建并显示图片*/
var myPic = (function() {
var pic = document.createElement("img");
document.body.appendChild(pic);

return {
setSrc: function(src) {
pic.src = src;
}
};
})();

/*代理模块,实现在图片加载完之前显示loading图片*/
var ProxyPic = (function() {
var img = new Image();
img.onload = function() {
document.getElementById("loading_img").style.display = "none";
myPic.setSrc(this.src);
};

return {
setSrc: function(src) {
document.getElementById("loading_img").style.display = "block";
img.src = src;
}
};
})();

ProxyPic.setSrc("http://tupian.enterdesk.com/2013/mxy/12/10/15/3.jpg");

二、缓存代理

使用高阶函数动态创建代理的技术也叫做“记忆”,是一种以空间换时间的技术。

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
29
/*业务模块,这里以阶乘为例*/
var factorial = function(){
var res=1;
var n=arguments[0];
for(var i=1;i<=n;i++){
res*=i;
}
return res;
};

/*缓存代理工厂函数*/
var createProxyHandler=function(fn){
var cache=[];
return function(){
var key=Array.prototype.join.call(arguments,'-');
if(key in cache){
console.log("cache exits");
return cache[key];
}else{
return cache[key]=fn.apply(this,arguments);
}
};
};

/*创建带缓存代理的技术*/
var proxyFactorial=createProxyHandler(factorial);

console.log(proxyFactorial(5)); //120
console.log(proxyFactorial(5)); //cache exits 120