代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問
代理模式的用處(個人理解):為了保障當前對象的單一職責(相對獨立性),而需要創建另一個對象來處理調用當前對象之前的一些邏輯以提高代碼的效率、狀態判斷等。
代理模式中最常用的是虛擬代理和緩存代理
一、虛擬代理
虛擬代理是把一些開銷很大的對象,延遲到真正需要它的時候才去創建執行
示例: 虛擬代理實現圖片預加載
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 設計模式與開發實踐 >>