代理模式是爲一個對象提供一個代用品或佔位符,以便控制對它的訪問
代理模式的用處(我的理解):爲了保障當前對象的單一職責(相對獨立性),而須要建立另外一個對象來處理調用當前對象以前的一些邏輯以提升代碼的效率、狀態判斷等。
代理模式中最經常使用的是虛擬代理和緩存代理
1、虛擬代理
虛擬代理是把一些開銷很大的對象,延遲到真正須要它的時候纔去建立執行
示例: 虛擬代理實現圖片預加載
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 }
2、 緩存代理
緩存代理能夠爲一些開銷大的運算結果提供暫時的存儲,在下次運算時,若是傳遞進來的參數跟以前一致,則能夠返回前面的運算結果。
示例: 爲乘法、加法等建立緩存代理
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 設計模式與開發實踐 >>