代理模式

代理模式

@(记录)[读书笔记]

代理模式:为一个对象提供一个代用品或者占位符,以便控制它的访问。
关键点是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象。

保护代理

代理可以帮组本体拒绝一些请求,这些可以算上是保护本体的代理。
保护代理用于控制不同权限的对象对目标对象的访问,但在JavaScript并不容易实现保护代理,因为我们无法判断谁访问了某个对象。比较常用的是虚拟代理。

虚拟代理

虚拟代理,就是把一些开销很大的对象,延迟到真正需要它的时候才去创建。
使用虚拟代理实现图片的预加载:

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
var myImage = (function() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return {
setSrc: function(src) {
imgNode.src = src;
}
}
})();
//使用代理,在图片真正被加载好之前,页面中将出现一张占位的菊花图用来提示用户图片正在加载
var proxyImage = (function() {
var img = new Image();
img.onload = function() {
myImage.setSrc(this.src);
}
return {
setSrc: function(src) {
myImage.setSrc('http://oemsj8g9f.bkt.clouddn.com/5-51.gif');
img.src = src;
}
}
})();
proxyImage.setSrc('http://oemsj8g9f.bkt.clouddn.com/avatar.png');

不使用代理模式也可以实现图片预加载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var myImage = (function() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
var img = new image();
img.onload = function() {
imgNode.src = img.src;
}
return {
setSrc: function(src) {
imgNode.setSrc('http://oemsj8g9f.bkt.clouddn.com/5-51.gif');
img.src = src;
}
}
})();
myImage.setSrc('http://oemsj8g9f.bkt.clouddn.com/avatar.png');

使用代理模式的意义是为了遵循面向对象设计的一个原则——单一职责原则;
单一职责原则指的是,就是一个类应该仅有一个引起它变化的原因。如果一个对象承担了多项职责,那么这个对象就变得巨大,引起它变化的原因就会有多个,将多个职责聚合在一个对象就会使对象的设计脆弱和低内聚,不利于系统的测试和修改。

虚拟代理还可以用在HTTP请求的合并上(优化程序之一是减低网络请求);例如在同步一些列文件的时候,可以等待一小段时间,打包文件再同步上传减低网络请求。

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
30
var synchronousFile = function(id) {
console.log('开始同步文件,id为:' + id);
};
var proxySynchronousFile = (function() {
var cache = [],
timer;
return function(id) {
cache.push(id);
if (timer) {
return;
}
timer = setTimeout(function() {
synchronousFile(cache.join(','));
clearTimeout(timer);
timer = null;
cache.length = 0;
}, 2000);//等待2s再同步上传文件
}
})();
var checkbox = document.getElementsByTagName('input');
for(var i = 0,c; c = checkbox[i++];) {
c.onclick = function() {
if (this.checked === true) {
proxySynchronousFile(this.id);
}
}
}

缓存代理

其实就是储存已经计算的结果,再次计算时直接返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var mult = function() {
console.log('开始计算乘积');
var a = 1;
for(var i = 0, l = arguments.length; i < l; i++) {
a = a * arguments[i];
}
return a;
}
var proxyMult = (function() {
var cache = {};
return function() {
var args = Array.prototype.join.call(arguments, ',');
if (args in cache) {
return cache[args];
}
return cache[args] = mult.apply(this, arguments);
}
})();
proxyMult(1,2,3,4);//24
proxyMult(2,3,4,5);//120

坚持原创技术分享,您的支持将鼓励我继续创作!