定義:
代理模式:為一個對象找一個替代對象,以便對原對象進行訪問。在我的理解鍾,代理就類似於第三方,比如,電視劇中的某大亨出現意外情況的時候,基本都會讓律師全權代理,不會直接和大亨進行溝通,律師所做的事情就可以理解為代理模式。還有就是代購這個職業,比如我們因為各種原因不能出國去購買某種化妝品,這時候,代購的作用就顯而易見了,她可以代替你出國去購買你所需要的東西,而你不需要出國。這也是符合代理模式的。
在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介作用。
使用代理的原因是我們不願意或者不想對原對象直接進行操作。
先來一個簡單的例子,代購買化妝品的例子
// 化妝品類 var cosmetic = function(name) { this.name = name; } cosmetic.prototype.getName = function() { return this.name; } // 定義不能出國的人 var people = { buyCosmetic: function(name) { console.log('請幫我代購'+ name) } } // 定義代購對象 var purchasing = { buyCosmetic: function(cosmetic) { people.buyCosmetic(cosmetic.getName()) } }
purchasing.buyCosmetic(new cosmetic('口紅'))
ES6所提供Proxy構造函數能夠讓我們輕松的使用代理模式:
var proxy = new Proxy(target, handler);
Proxy構造函數傳入兩個參數,第一個參數target表示所要代理的對象,第二個參數handler也是一個對象用來設置對所代理的對象的行為。如果想知道Proxy的具體使用方法,可參考阮一峰的《 ECMAScript入門 - Proxy 》。
虛擬代理:是把一些開銷很大的對象,延遲到真正需要它的時候才去創建執行
我們在瀏覽一些購物商城的時候,會發現,當網絡不太好的情況下,有些圖片是加載不出來的,會有暫無圖片的一張圖片去代替它實際的圖片,等網路圖片加載完成之后,暫無圖片就會被實際的圖片代替。這就是使用的圖片的懶加載。圖片的懶加載也可是使用虛擬代理的模式來進行設計。
// 圖片懶加載 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) { console.log('src', src) myImage.setSrc('http://seopic.699pic.com/photo/40007/8839.jpg_wh1200.jpg'); img.src = src; } } })(); proxyImage.setSrc('http://seopic.699pic.com/photo/40006/7735.jpg_wh1200.jpg')
緩存代理::可以作為一些開銷大的運算結果提供暫時的存儲,下次運算時,如果傳遞進來堵塞參數跟之前一致,則可以直接返回前面存儲的運算結果。
例如,前后端分離,向后端請求分頁的數據的時候,每次頁碼改變時都需要重新請求后端數據,我們可以將頁面和對應的結果進行緩存,當請求同一頁的時候,就不再請求后端的接口而是從緩存中去取數據。
const getFib = (number) => { if (number <= 2) { return 1; } else { return getFib(number - 1) + getFib(number - 2); } } const getCacheProxy = (fn, cache = new Map()) => { return new Proxy(fn, { apply(target, context, args) { const argsString = args.join(' '); if (cache.has(argsString)) { // 如果有緩存,直接返回緩存數據 console.log(`輸出${args}的緩存結果: ${cache.get(argsString)}`); return cache.get(argsString); } const result = fn(...args); cache.set(argsString, result); return result; } }) } const getFibProxy = getCacheProxy(getFib); getFibProxy(40); // 102334155getFibProxy(40); // 輸出40的緩存結果: 102334155
使用場景:
代理模式的類型較多,不同類型的代理模式有不同的優缺點,它們應用於不同的場合:
(1) 當客戶端對象需要訪問遠程主機中的對象時可以使用遠程代理。
(2) 當需要用一個消耗資源較少的對象來代表一個消耗資源較多的對象,從而降低系統開銷、縮短運行時間時可以使用虛擬代理,例如一個對象需要很長時間才能完成加載時。
(3) 當需要為某一個被頻繁訪問的操作結果提供一個臨時存儲空間,以供多個客戶端共享訪問這些結果時可以使用緩沖代理。通過使用緩沖代理,系統無須在客戶端每一次訪問時都重新執行操作,只需直接從臨時緩沖區獲取操作結果即可。
(4) 當需要控制對一個對象的訪問,為不同用戶提供不同級別的訪問權限時可以使用保護代理。
(5) 當需要為一個對象的訪問(引用)提供一些額外的操作時可以使用智能引用代理。
優缺點:
優點:代理模式能夠將代理對象與被調用的對象分離,降低了系統的耦合度。代理模式在客戶端和目標對象之間起到一個中介作用,這樣,可以起到保護目標對象的作用。代理對象也可以對目標對象調用之前進行其他的操作。
缺點:; 增加系統的復雜度
