JavaScript設計模式之代理模式詳解
更新時間:2017年06月09日 14:49:08 作者:Stinchan
這篇文章主要為大家詳細介紹了JavaScript設計模式之代理模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
代理模式是非常常見的模式,比如我們使用的VPN工具,明星的經(jīng)紀人,都是代理模式的例子。但是,有人會疑問,明明可以直接訪問對象,為什么中間還要加一個殼呢?這也就說到了代理模式的好處。在我看來,代理模式最大的好處,就是在不動原有對象的同時,可以給原有對象增加一些新的特性或者行為。
/**
* pre:代理模式
* 小明追求A,B是A的好朋友,小明比較靦腆,不好意思直接將花交給A,
* 于是小明將花交給B,再由B交給A.
*/
//----------- 示例1 ---------
// 不使用代理
var Flower = function() {};
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower();
target.receiveFlower(flower);
}
};
var A = {
receiveFlower: function(flower) {
console.log("收到花:" + flower);
}
};
xiaoming.sendFlower(A);
// ----------- 示例2 --------------
// 使用代理1
var Flower = function() {};
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower();
B.receiveFlower(flower);
}
};
var B = {
receiveFlower: function(flower) {
A.receiveFlower(flower);
}
};
var A = {
receiveFlower: function(flower) {
console.log("收到花:" + flower);
}
};
xiaoming.sendFlower(B);
//------------- 示例3 ---------------
/*
* 使用代理2
* 從示例1和示例2,看不出使用代理有什么用處,B只不過是從中間轉(zhuǎn)手了一次。
* 接下來,我們想一下。給喜歡的人送花,怎樣才能提高成功率呢?
* 我們都知道,人有心情好和心情差的時候,當美女心情好的時候,送花成功的概率自然要大些。
* 于是,我們將代理升級,監(jiān)聽美女的心情,心情好的時候再給她送花。
* 為了演示,我們假設2秒后,A的心情變好。
*/
var Flower = function() {};
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower();
B.receiveFlower(flower);
}
};
var B = {
receiveFlower: function(flower) {
A.listenGoodMood(function() {
A.receiveFlower(flower);
});
}
};
var A = {
receiveFlower: function(flower) {
console.log("收到花:" + flower);
},
listenGoodMood: function(fn) {
setTimeout(function() {
fn.apply(this, arguments);
}, 2000);
}
};
xiaoming.sendFlower(B);
// ---------- 示例4 ---------------
/*
* 【代理模式用處】:虛擬代理
* 這里以加載圖片為例,我們都知道當網(wǎng)絡不暢以及圖片過大時,圖片加載都比較慢,
* 為了更好的用戶體驗,我們都會在原圖片未加載完成前,加上loading圖片。
* */
//--4 _01未使用代理--
var myImage = (function() {
var imgNode = document.createElement("img");
document.body.appendChild(imgNode);
return {
setSrc: function(src) {
this.imgNode.src = src;
}
}
})();
myImage.setSrc("xxx");
//--4_02使用代理--
var proxyMyImage = (function() {
var img = new Image();
img.onload = function() {
myImage.setSrc(this.src);
};
return {
setSrc: function(src) {
myImage.setSrc("loading.jpg");
img.src = src;
}
}
})();
proxyMyImage.setSrc("xxx");
/*
* [注]:這里可以看到代理模式的好處:在不改變原有接口的同時,可以為系統(tǒng)添加新的行為。
*/
//--------- 示例5---------------
/*
* 【代理模式用處】:合并http請求
* 這里以選擇文件同步為例。
* 以往用戶同步文件,在用戶選中的時候就觸發(fā),這種方法做到了實時性,但無疑增加了網(wǎng)絡的開銷。
* 實際在使用的過程中,往往并不需要立刻就同步。
* 以下通過代理模式,將在用戶選中文件2秒后進行同步請求。
* */
// --- 包含一段html代碼,請自行添加到一個文件中 ------
<html>
<body>
<button id="input">點我上傳</button>
<input type="checkbox" id="1"></input>1
<input type="checkbox" id="2"></input>2
<input type="checkbox" id="3"></input>3
<input type="checkbox" id="4"></input>4
<input type="checkbox" id="5"></input>5
<input type="checkbox" id="6"></input>6
<input type="checkbox" id="7"></input>7
<input type="checkbox" id="8"></input>8
<input type="checkbox" id="9"></input>9
</body>
</html>
// -- 上傳文件 --
var synchronizeFile = function(id) {
console.log("開始同步文件:" + id);
};
var proxySynchronizeFiles = (function() {
var fileCache = [],
timer;
return function(id) {
fileCache.push(id);
if(timer) {
return;
}
timer = setTimeout(function() {
synchronizeFile(fileCache.join(","));
clearTimeout(timer);
timer = null;
checkArr.length = 0;
}, 2000);
}
})();
var checkArr = document.getElementsByTagName("input");
for(var i = 0, c; c = checkArr[i++];) {
c.onclick = function() {
if(this.checked == true) {
proxySynchronizeFiles(this.id);
}
}
}
// ------------ 示例6 -----------------
/*
* 【代理模式用處】:緩存代理
* 以計算器為例,比如計算某些數(shù)的乘積,當參數(shù)重復時,我們希望不用重復計算,直接返回結(jié)果。
* 以下用到代理模式做緩存。
*/
var mult = function() {
if(!arguments) {
console.log("請輸入?yún)?shù)");
return;
}
var a = 1;
for(var i = 0, b; b = arguments[i++];) {
a = a * b;
}
return a;
};
var proxyMult = (function() {
var cache = {};
return function() {
var str = Array.prototype.join.call(arguments, ",");
if(str in cache) {
console.log("重復return.");
return cache[str];
}
return cache[str] = mult.apply(this, arguments);
}
})();
console.log(proxyMult(2, 3, 4));
console.log(proxyMult(2, 3, 4));
//------------ 示例7 --------------
/*
* 緩存代理升級 - 通用版計算
*
*/
var mult = function() {
if(!arguments) {
return;
}
var t = 1;
for(var i = 0, a; a = arguments[i++];) {
t = t * a;
}
return t;
};
var plus = function() {
if(!arguments) {
return;
}
var t = 0;
for(var a of arguments) {
t += a;
}
return t;
};
var createProxyCaculate = function(fn) {
var cache = {};
return function() {
var str = Array.prototype.join.call(arguments, ",");
if(str in cache) {
console.log("重復return" + str);
return cache[str];
}
return cache[str] = fn.apply(this, arguments);
}
};
var proxyMult = createProxyCaculate(mult);
var proxyPlus = createProxyCaculate(plus);
console.log(proxyMult(2, 3, 4));
console.log(proxyMult(2, 3, 4));
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript基于inquirer封裝一個控制臺文件選擇器
這篇文章主要介紹了JavaScript基于inquirer封裝一個控制臺文件選擇器,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-08-08
Vue3基于countUp.js實現(xiàn)數(shù)字滾動的插件
本文主要介紹了Vue3基于countUp.js實現(xiàn)數(shù)字滾動的插件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04

