javascript
javascript设计模式-代理模式
代理的結(jié)構(gòu)
代理模式的最基本形式就是對訪問進(jìn)行控制。代理對象和另一個對象實現(xiàn)的是同樣的接口。代理對象只是節(jié)制對本體的訪問。
代理對象不會在另一個對象上添加或修改方法,也不會簡化對象的接口,所有對方法的調(diào)用都會被傳遞給本體。
虛擬代理
用于控制對那種創(chuàng)建開銷很大的本體的訪問。他會把本體的實例化推遲到有方法被調(diào)用的時候。
代理對象具有與本體類實例對象的相同的方法,想操作本體類實例對象必須先通過代理對象,從而實現(xiàn)對本體類實例對象的控制。
創(chuàng)建虛擬代理的通用模式
示例:圖片預(yù)加載
let myImage = (function (src) {let node = document.createElement('img');document.body.appendChild(node);return {setSrc(src){node.src = src;}} })();let proxyImg = (function (){let img = new Image();img.onload = function (){myImage.setSrc(this.src);}return {setSrc(src){myImage.setSrc('');img.src=src;}} })();示例:合并http請求
當(dāng)有多個多選框,用戶點擊多選框進(jìn)行上傳文件時,當(dāng)用戶點擊的過快,會導(dǎo)致服務(wù)器壓力過大,此時需要通過虛擬代理,減少在某一時刻發(fā)送的請求數(shù)量。
let syncrequest = function (ids) {console.log('開始同步文件', ids); }let proxSync = (function () {let cache = [],timer;return function (id) {cache.push(id);if (timer) {return;}timer = setTimeout(() => {syncrequest(cache.join(','));clearTimeout(timer);timer = null;}, 2000);} })();let checkbox = document.getElementsByTagName('input'); for(let i = 0, c; c = checkbox[i++];){c.onclick = function(){if(this.checked === true){proxSync(this.id);}} }遠(yuǎn)程代理
遠(yuǎn)程代理用于訪問另一個環(huán)境中的對象。
這種方式很難照搬到JavaScript中:
控制對其他語言中的本體的訪問。這種本體可能是Web服務(wù)資源,也可能是PHP對象,很難說你所使用的是什么模式。
安全代理
安全代理:用來控制真實對象的訪問權(quán)限,即滿足條件的可以訪問,不滿足條件的不能訪問
class Order {constructor(productName, productCount, orderUserName) {this.productName = productName;this.productCount = productCount;this.orderUser = orderUserName;}// 獲取訂單中產(chǎn)品的名稱getProductName() {return this.productName;}// 設(shè)置訂單中產(chǎn)品的名稱setProductName(productName) {this.productName = productName;}// 獲取訂單的用戶getOrderUserName() {return this.orderUserName;}// 設(shè)置訂單的用戶setOrderUserName(orderUserName) {this.orderUserName = orderUserName;}// 獲取產(chǎn)品數(shù)量getProductCount() {return this.oproductCount;}// 設(shè)置產(chǎn)品數(shù)量setProductCount(productCount) {this.productCount = productCount;}}class ProxyObject {constructor(realObject) {this.realObject = realObject;}// 獲取訂單中產(chǎn)品的名稱getProductName() {if (userName === this.realObject.orderUserName) {return this.realObject.productName;}}// 設(shè)置訂單中產(chǎn)品的名稱setProductName(productName, userName) {if (userName === this.realObject.orderUserName) {this.realObject.productName = productName;}}// 獲取訂單的用戶getOrderUserName() {if (userName === this.realObject.orderUserName) {return this.realObject.orderUserName;}}// 設(shè)置訂單的用戶setOrderUserName(orderUserName, userName) {if (userName === this.realObject.orderUserName) {this.realObject.orderUserName = orderUserName;}}// 獲取產(chǎn)品數(shù)量getProductCount() {return this.realObject.productCount;}// 設(shè)置產(chǎn)品數(shù)量setProductCount(productCount, userName) {if (userName === this.realObject.orderUserName) {this.realObject.productCount = productCount;}}}let order = new Order('西瓜', 1, 'wang');let subject = new ProxyObject(order);let productCount = subject.getProductCount(order.orderUserName);console.log(productCount);緩存代理
緩存代理可以為一些開銷大的運算結(jié)果提供暫時的存儲,在下次運算時,如果傳遞進(jìn)來的參數(shù)跟之前一致,則可以直接返回前面存儲的運算結(jié)果
以計算乘積的程序為例,mult()方法用于計算乘積并返回計算后的結(jié)果,proxyMult用于把mult()計算后的結(jié)果緩存,當(dāng)有相同的參數(shù)時,把參數(shù)對應(yīng)的結(jié)果返回,如果沒有相同的參數(shù),把參數(shù)的乘積計算后緩存然后返回結(jié)果。
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( 1, 2, 3, 4 ); // 輸出:24代理模式的適用場合
虛擬代理是一種優(yōu)化模式。如果有些類或?qū)ο笮枰褂么罅績?nèi)存保存其數(shù)據(jù),而你并不需要在實例化后立即訪問這些數(shù)據(jù), 或者, 構(gòu)造函數(shù)需要進(jìn)行大量計算,此時需要使用虛擬代理模式。
優(yōu)缺點
優(yōu)點
控制開銷較大的對象的創(chuàng)建時機(jī)。
缺點
代理可以隱藏大量復(fù)雜行為。
總結(jié)
以上是生活随笔為你收集整理的javascript设计模式-代理模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android contentprovi
- 下一篇: JavaScript 2 基本语法