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


Posted in Javascript onJune 09, 2017

代理模式是非常常见的模式,比如我们使用的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 相关文章推荐
javascript setAttribute, getAttribute 在不同浏览器上的不同表现
Aug 05 Javascript
javascript string字符串优化问题
Jul 31 Javascript
javascript 快速排序函数代码
May 30 Javascript
js实现checkbox全选、不选与反选的方法
Feb 09 Javascript
Node.js环境下JavaScript实现单链表与双链表结构
Jun 12 Javascript
Angularjs 创建可复用组件实例代码
Oct 09 Javascript
JS触摸事件、手势事件详解
May 04 Javascript
快速掌握jquery分页插件jqPaginator的使用方法
Aug 09 jQuery
vue实现全选和反选功能
Aug 31 Javascript
JS正则表达式完美实现身份证校验功能
Oct 18 Javascript
在vue项目中引入highcharts图表的方法(详解)
Mar 05 Javascript
vue.js项目nginx部署教程
Apr 05 Javascript
vue.js+Echarts开发图表放大缩小功能实例
Jun 09 #Javascript
vue2 中如何实现动态表单增删改查实例
Jun 09 #Javascript
JS创建Tag标签的方法详解
Jun 09 #Javascript
JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)
Jun 09 #Javascript
JS实现的随机排序功能算法示例
Jun 09 #Javascript
JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结(整理)
Jun 09 #jQuery
JQuery.dataTables表格插件添加跳转到指定页
Jun 09 #jQuery
You might like
PHP 操作文件的一些FAQ总结
2009/02/12 PHP
PHP AjaxForm提交图片上传并显示图片源码
2016/11/29 PHP
YII2框架中behavior行为的理解与使用方法示例
2020/03/13 PHP
javascript温习的一些笔记 基础常用知识小结
2011/06/22 Javascript
jquery右下角弹出提示框示例代码
2013/10/08 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
nodejs开发微博实例
2015/03/25 NodeJs
Bootstrap布局组件应用实例讲解
2016/02/17 Javascript
jQuery插件编写步骤详解
2016/06/03 Javascript
详解Node.js如何开发命令行工具
2016/08/14 Javascript
利用D3.js实现最简单的柱状图示例代码
2016/12/09 Javascript
jQuery UI仿淘宝搜索下拉列表功能
2017/01/10 Javascript
用JS实现简单的登录验证功能
2017/07/28 Javascript
vue实现的网易云音乐在线播放和下载功能案例
2019/02/18 Javascript
Vue函数式组件-你值得拥有
2019/05/09 Javascript
jQuery实现二级导航菜单的示例
2020/09/30 jQuery
[02:28]DOTA2亚洲邀请赛附加赛 RECAP赛事回顾
2015/01/29 DOTA
[04:04]DOTA2亚洲邀请赛比赛场馆&酒店全攻略
2017/03/23 DOTA
在Mac OS上搭建Python的开发环境
2015/12/24 Python
python 获取网页编码方式实现代码
2017/03/11 Python
Python实现多条件筛选目标数据功能【测试可用】
2018/06/13 Python
在dataframe两列日期相减并且得到具体的月数实例
2018/07/03 Python
Python实现将元组中的元素作为参数传入函数的操作
2020/06/05 Python
python cv2.resize函数high和width注意事项说明
2020/07/05 Python
浅谈如何使用python抓取网页中的动态数据实现
2020/08/17 Python
python 贪心算法的实现
2020/09/18 Python
Python:__eq__和__str__函数的使用示例
2020/09/26 Python
ProBikeKit新西兰:自行车套件,跑步和铁人三项装备
2017/04/05 全球购物
上海中网科技笔试题
2012/02/19 面试题
新媒传信软件测试面试题
2013/02/24 面试题
矫正人员思想汇报
2014/01/08 职场文书
就业协议书范本
2014/04/11 职场文书
领导班子整改措施
2014/10/24 职场文书
2015年教务处干事工作总结
2015/07/22 职场文书
老兵退伍感言
2015/08/03 职场文书
PYTHON InceptionV3模型的复现详解
2022/05/06 Python