JavaScript设计模式之代理模式详解

代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子。但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处。在我看来,代理模式最大的好处,就是在不动原有对象的同时,可以给原有对象增加一些新的特性或者行为。

/**

* 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只不过是从中间转手了一次。

* 接下来,我们想一下。给喜欢的人送花,怎样才能提高成功率呢?

* 我们都知道,人有心情好和心情差的时候,当美女心情好的时候,送花成功的概率自然要大些。

* 于是,我们将代理升级,监听美女的心情,心情好的时候再给她送花。

* 为了演示,我们假设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 ---------------

/*

* 【代理模式用处】:虚拟代理

* 这里以加载图片为例,我们都知道当网络不畅以及图片过大时,图片加载都比较慢,

* 为了更好的用户体验,我们都会在原图片未加载完成前,加上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");

/*

* [注]:这里可以看到代理模式的好处:在不改变原有接口的同时,可以为系统添加新的行为。

*/

//--------- 示例5---------------

/*

* 【代理模式用处】:合并http请求

* 这里以选择文件同步为例。

* 以往用户同步文件,在用户选中的时候就触发,这种方法做到了实时性,但无疑增加了网络的开销。

* 实际在使用的过程中,往往并不需要立刻就同步。

* 以下通过代理模式,将在用户选中文件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 -----------------

/*

* 【代理模式用处】:缓存代理

* 以计算器为例,比如计算某些数的乘积,当参数重复时,我们希望不用重复计算,直接返回结果。

* 以下用到代理模式做缓存。

*/

var mult = function() {

if(!arguments) {

console.log("请输入参数");

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));

以上是 JavaScript设计模式之代理模式详解 的全部内容, 来源链接: utcz.com/z/353189.html

回到顶部