代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问
代理模式的用处(个人理解):为了保障当前对象的单一职责(相对独立性),而需要创建另一个对象来处理调用当前对象之前的一些逻辑以提高代码的效率、状态判断等。
代理模式中最常用的是虚拟代理和缓存代理
一、虚拟代理
虚拟代理是把一些开销很大的对象,延迟到真正需要它的时候才去创建执行
示例: 虚拟代理实现图片预加载
1 // 图片加载函数
2 var myImage = (function(){
3 var imgNode = document.createElement("img");
4 document.body.appendChild(imgNode);
5
6 return {
7 setSrc: function(src) {
8 imgNode.src = src;
9 }
10 }
11 })();
12
13 // 引入代理对象
14 var proxyImage = (function(){
15 var img = new Image;
16 img.onload = function(){
17 // 图片加载完成,正式加载图片
18 myImage.setSrc( this.src );
19 };
20 return {
21 setSrc: function(src){
22 // 图片未被载入时,加载一张提示图片
23 myImage.setSrc("file://c:/loading.png");
24 img.src = src;
25 }
26 }
27 })();
28
29 // 调用代理对象加载图片
30 proxyImage.setSrc( "http://images/qq.jpg");
示例: 虚拟代理合并HTTP请求
假设一个功能需要频繁的进行网络请求,这会造成相当大的开销,解决方案是通过一个代理函数来收集一段时间之内的请求,一次性发给服务器。
例如:做一个文件同步的功能,当我们选中一个文件时,就同步到另外一台备用服务器上
1 // 文件同步函数
2 var synchronousFile = function( id ){
3 console.log( "开始同步文件,id为:" + id );
4 }
5 // 使用代理合并请求
6 var proxySynchronousFile = (function(){
7 var cache = [], // 保存一段时间内需要同步的ID
8 timer; // 定时器指针
9
10 return function( id ){
11 cache[cache.length] = id;
12 if( timer ){
13 return;
14 }
15
16 timer = setTimeout( function(){
17 proxySynchronousFile( cache.join( "," ) ); // 2s 后向本体发送需要同步的ID集合
18 clearTimeout( timer ); // 清空定时器
19 timer = null;
20 cache = []; // 晴空定时器
21 },2000 );
22 }
23 })();
24
25 // 绑定点击事件
26 var checkbox = document.getElementsByTagName( "input" );
27
28 for(var i= 0, c; c = checkbox[i++]; ){
29 c.onclick = function(){
30 if( this.checked === true ){
31 // 使用代理进行文件同步
32 proxySynchronousFile( this.id );
33 }
34 }
35 }
二、 缓存代理
缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递进来的参数跟之前一致,则可以返回前面的运算结果。
示例: 为乘法、加法等创建缓存代理
1 // 计算乘积
2 var mult = function(){
3 var a = 1;
4 for( var i = 0, l = arguments.length; i < l; i++){
5 a = a * arguments[i];
6 }
7 return a;
8 };
9 // 计算加和
10 var plus = function () {
11 var a = 0;
12 for( var i = 0, l = arguments.length; i < l; i++ ){
13 a += arguments[i];
14 }
15 return a;
16 };
17 // 创建缓存代理的工厂
18 var createProxyFactory = function( fn ){
19 var cache = {}; // 缓存 - 存放参数和计算后的值
20 return function(){
21 var args = Array.prototype.join.call(arguments, "-");
22 if( args in cache ){ // 判断出入的参数是否被计算过
23 console.log( "使用缓存代理" );
24 return cache[args];
25 }
26 return cache[args] = fn.apply( this, arguments );
27 }
28 };
29 // 创建代理
30 var proxyMult = createProxyFactory( mult ),
31 proxyPlus = createProxyFactory( plus );
32
33 console.log( proxyMult( 1, 2, 3, 4 ) ); // 输出: 24
34 console.log( proxyMult( 1, 2, 3, 4 ) ); // 输出: 缓存代理 24
35 console.log( proxyPlus( 1, 2, 3, 4 ) ); // 输出: 10
36 console.log( proxyPlus( 1, 2, 3, 4 ) ); // 输出: 缓存代理 10
阅读参考书籍 - << JavaScript 设计模式与开发实践 >>