代理模式是非常常见的模式,比如我们使用的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设计模式_03_代理模式的更多相关文章

  1. JavaScript设计模式之代理模式

    一.代理模式概念 代理,顾名思义就是帮助别人做事,GoF对代理模式的定义如下: 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问.代理模式使得代理对象控制具体对象的引用.代理几乎可 ...

  2. JavaScript 设计模式之代理模式

    一.代理模式概念解读 1.代理模式概念文字解读 代理,顾名思义就是帮助别人做事,GOF对代理模式的定义如下: 代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问.代理模式使得代理对象 ...

  3. 第三章 --- 关于Javascript 设计模式 之 代理模式

    第一.定义: 代理模式是为一个对象提供代用品或者占位符,以便控制对它的访问. 比如说,某男生小明想向他的女神 A 表白,刚好小明认识的一个女生B 和 女神A 是好朋友,那么小明就想让 女生B 帮忙送花 ...

  4. 学习javascript设计模式之代理模式

    1.代理模式为一个对象提供一个代用品或占位符,以便控制对它的访问. 2.不用代理模式: 客户 -> 本体  使用代理模式:  客户 -> 代理 -> 本体 3.例子场景1 点击操作与 ...

  5. JavaScript设计模式(代理模式)

    一.简单的单例模式: 1.未使用代理模式的情况:小明直接给女神送花 var Flower = function() {} var xiaoming = { sendFlower: function( ...

  6. JavaScript设计模式-19.代理模式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. C#设计模式(13)——代理模式(Proxy Pattern)

    一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...

  8. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  9. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

随机推荐

  1. STM32定时器

    /*****************************************************************************初始化定时器**************** ...

  2. Docker 架构详解 - 每天5分钟玩转容器技术(7)

    Docker 的核心组件包括: Docker 客户端 - Client Docker 服务器 - Docker daemon Docker 镜像 - Image Registry Docker 容器 ...

  3. LeanCloud 调研报告

    LeanCloud 是一家做后端即服务(BaaS)的厂商,目标是让移动互联网开发者能更加方便的开发应用. 出于工作关系,对 leancloud 进行了一番调研:主要目标是学习其后端即服务的产品化思路等 ...

  4. sass学习入门篇(三)

    这章我们讲“嵌套”,嵌套包括两种:一,选择器嵌套.二是属性的嵌套.一般用选择器嵌套居多 一,选择器嵌套:指的是在一个选择器中嵌套另一个选择器来实现继承.使用&表示父元素选择器 li{ floa ...

  5. FrameBuffer系列 之 一点资源

    Iamonlyme的FrameBuffer编程实例http://download.csdn.net/detail/iamonlyme/6512955 light588的通过framebuffer直接写 ...

  6. H5前端框架推荐合集

    Ionic ionic 吧开发流程都帮你做好了,已经不再是单纯的UI框架,而是开发框架了,非常适合快速开发.基于angular2,丰富的UI组件,大大改进的编程模型, Semantic UI 中文官网 ...

  7. seajs的那些坑

    seajs是what? 先看段代码: var loder = {}; var define = loder.define = function(id,deps,factory){ loader[id] ...

  8. bootstrap+masonry.js写瀑布流

    最近在用bootstrap写一个网站,其中有个图文展示的页面要用到瀑布流的效果.因为项目要求,项目要以bootstrap为基准,不准私自添加内联样式.内部样式,所以,自己写瀑布流就不行了,所以,根据要 ...

  9. Mysql求百分比

    根据相应条件抽出相应count数(myCount) 抽出总count数(totalCount) 计算百分比:myCount / totalCount * 100 四舍五入:使用ROUND函数ROUND ...

  10. 如何使用RSYNC搭建备份服务器

    1. RSYNC介绍 RSYNC是一款开源的,快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于unix/linux/windows等多种操作系统平台. 远程数 ...