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判断单选框或复选框是否选中方法集锦
Apr 04 Javascript
jQuery的运行机制和设计理念分析
Apr 05 Javascript
DOM基础教程之使用DOM设置文本框
Jan 20 Javascript
JS的数组迭代方法
Feb 05 Javascript
JS实现禁止鼠标右键的功能
Oct 15 Javascript
Vue.js使用v-show和v-if的注意事项
Dec 13 Javascript
Javascript的this用法
Jan 16 Javascript
JS实现PC手机端和嵌入式滑动拼图验证码三种效果
Feb 15 Javascript
Javacript中自定义的map.js  的方法
Nov 26 Javascript
layui table 列宽百分比显示的实现方法
Sep 28 Javascript
解决$store.getters调用不执行的问题
Nov 08 Javascript
vue实现在线学生录入系统
May 30 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
构建简单的Webmail系统
2006/10/09 PHP
php采集内容中带有图片地址的远程图片并保存的方法
2015/01/03 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
2019/07/03 PHP
Laravel 修改验证异常的响应格式实例代码详解
2020/05/25 PHP
jquery 1.3.2 IE8中的一点点的小问题解决方法
2009/07/10 Javascript
有效的捕获JavaScript焦点的方法小结
2009/10/08 Javascript
JQuery Tips(4) 一些关于提高JQuery性能的Tips
2009/12/19 Javascript
js下将字符串当函数执行的方法
2011/07/13 Javascript
Javascript实现的常用算法(如冒泡、快速、鸽巢、奇偶等)
2014/04/29 Javascript
一张表格告诉你windows.onload()与$(document).ready()的区别
2014/05/16 Javascript
javascript实现可拖动变色并关闭层窗口实例
2015/05/15 Javascript
javascript实现倒计时(精确到秒)
2015/06/26 Javascript
浅谈JavaScript 执行环境、作用域及垃圾回收
2016/05/31 Javascript
微信小程序 数据绑定及运算的简单实例
2017/09/20 Javascript
Vue.js中对css的操作(修改)具体方式详解
2018/10/30 Javascript
谈谈为什么你的 JavaScript 代码如此冗长
2019/01/30 Javascript
微信小程序登录数据解密及状态维持实例详解
2019/05/06 Javascript
js简单遍历获取对象中的属性值的方法示例
2019/06/19 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
读写json中文ASCII乱码问题的解决方法
2016/11/05 Python
python利用正则表达式搜索单词示例代码
2017/09/24 Python
python 接口测试response返回数据对比的方法
2018/02/11 Python
在python中pandas读文件,有中文字符的方法
2018/12/12 Python
Python中出现IndentationError:unindent does not match any outer indentation level错误的解决方法
2020/04/18 Python
使用OpenCV-python3实现滑动条更新图像的Canny边缘检测功能
2019/12/12 Python
Python如何实现远程方法调用
2020/08/07 Python
10款最佳Python开发工具推荐,每一款都是神器
2020/10/15 Python
阿玛尼化妆品美国官网:Giorgio Armani Beauty
2017/02/02 全球购物
override和overload的区别
2016/03/09 面试题
实习教师自我鉴定
2013/12/12 职场文书
初婚初育证明
2014/01/14 职场文书
偷看我的初中毕业鉴定
2014/01/29 职场文书
学生会感恩节活动方案
2014/10/11 职场文书
毕业答辩开场白范文
2015/05/27 职场文书
《曹冲称象》教学反思
2016/02/20 职场文书
linux目录管理方法介绍
2022/06/01 Servers