首页 > 编程 > JavaScript > 正文

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

2019-11-19 16:22:34
字体:
来源:转载
供稿:网友

代理模式是非常常见的模式,比如我们使用的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 --------------// 使用代理1var 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));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表