详解javascript设计模式三:代理模式


Posted in Javascript onMarch 25, 2019

代理模式是一种对程序对象进行控制性访问的一类解决方案。

引入代理模式,其实是为了实现单一职责的面向对象设计原则。

单一职责其实就是指在一个类中(js中通常指对象和函数等),应仅有一个引起它变化的原因。这样会帮助程序设计具有良好的健壮和高内聚特性,从而当变化发生时,程序设计会尽量少的受到意外破坏。

代理模式有多种方法,保护代理、远程代理、虚拟代理、缓存代理等。

但在javascript中,代理模式最常用到的两种方法是虚拟代理和缓存代理。

虚拟代理

在理解虚拟代理时,可以将其想象为一个经纪人,客户程序需要通过这个虚拟代理(经纪人)来调用本体对象的方法。

虚拟代理示例demo1: 图片loading预加载

//通过虚拟代理实现图片预加载
//代理模式进行图片预加载的实现思路是: 通过代理对象获取实际显示图片地址并进行加载,同时先让本体对象显示预加载图片,待代理对象将实际图片地址加载完毕后传递给本体对象进行显示即可。

//本体对象
var myImage = (function(){
  var imgNode = new Image()
  document.body.appendChild(imgNode)

  return {
    setSrc: function(src){
      imgNode.src = src
    }
  }
})()

//代理对象
var proxyImage = (function(){
  var img = new Image();     //1、代理对象新建一个img对象
  img.onload = function(){    //4、代理对象img加载真实图片src完成后将src传递给本体对象显示
    myImage.setSrc(this.src)
  }
  return {
    setProxySrc: function(src){
      myImage.setSrc('../images/loding.gif') //2、代理对象控制本体对象使用加载图片src
      img.src = src          //3、代理对象的img对象获取将要传递给本体对象的真实图片src
    }
  }
})()

//通过代理对象来对本体对象进行访问
proxyImage.setProxySrc('https://p1.ssl.qhimgs1.com/t0153297036f4471d81.jpg')

虚拟代理示例demo2:合并HTTP请求,减少网络请求资源消耗

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>代理模式 虚拟代理合并HTTP请求</title>
</head>
<body>
  <div>
    <input type="checkbox" id="1" />1
    <input type="checkbox" id="2" />2
    <input type="checkbox" id="3" />3
    <input type="checkbox" id="4" />4
    <input type="checkbox" id="5" />5
    <input type="checkbox" id="6" />6
    <input type="checkbox" id="7" />7
    <input type="checkbox" id="8" />8
    <input type="checkbox" id="9" />9
  </div>  
</body>
<script>
  //使用

  //本体对象
  var synchornurFile = function(id){
    console.log('开始同步:' + id);
  }

  var proxySynchornurFile = (function(){
    var cache = [],   //集合一段时间内需要同步的id
      timer;   //定时器

    return function(id){
      cache.push(id)

      if(timer){   //保证不会覆盖已经启动的定时器
        return
      }
      timer = setTimeout(function(){
        synchornurFile(cache.join(','))
        clearTimeout(timer)
        timer = null
        cache.length = 0
      }, 2000)
    }
  })()

  var check = document.getElementsByTagName('input')
  for(var i=0; i<check.length; i++){
    check[i].onclick = function(){
      if(this.checked === true){
        proxySynchornurFile(this.id)
      }
    }
  }
</script>
</html>

缓存代理

缓存代理可以为一些开销大的运算结果提供暂时存储,在下次运算时,如果传递进来的参数和之前的一致,则可以直接返回前面存储的结果

缓存代理示例demo: 计算乘积

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>代理模式-缓存代理</title>
</head>
<body>
  <input type="text" id="input1">*
  <input type="text" id="input2">
  <div id="result"></div>
  <button type="button" id="btn">计算</button>
</body>
<script>

  //缓存代理示例: 计算乘积
  //本体对象
  var calculate = function(){
    var a = 1;
    for(var i=0; i<arguments.length; i++){
      a = a*arguments[i]
    }
    return a;
  }

  //代理对象,创建缓存代理的工厂,参数fn可以为任意需要进行代理的函数,除了上述计算乘积的本体对象函数外,还可以是计算加减或进行其他操作的本体函数
  var proxyCalculate = function(fn){
    var resultCache = {};

    return function(){
      var args = Array.prototype.join.call(arguments, ',')
      if(args in resultCache){    //测试对象中是否有对应的name,有则直接返回该name的值
        return resultCache[args]
      }
      return resultCache[args] = fn.apply(this, arguments)
    }
  }


  document.getElementById('btn').onclick = function(){
    var v1 = document.getElementById('input1').value
    var v2 = document.getElementById('input2').value
    var result = proxyCalculate(calculate)(v1, v2)

    document.getElementById('result').innerHTML = result
  }

  //总结: 代理模式还有多种,比如保护代理、远程代理等,但js中常用的代理模式有虚拟代理和缓存代理两种。
</script>
</html>

在编写业务代码时,并不需要一开始就考虑是否使用代理模式,只要当发现使用代理模式更方便时,再编写代理对象即可。

以上所述是小编给大家介绍的javascript设计模式三:代理模式详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js下将阿拉伯数字每三位一逗号分隔(如:15000000转化为15,000,000)
Jun 02 Javascript
深入理解JavaScript系列(46):代码复用模式(推荐篇)详解
Mar 04 Javascript
使用JavaScript实现连续滚动字幕效果的方法
Jul 07 Javascript
Angular2 父子组件通信方式的示例
Jan 29 Javascript
vue+element的表格实现批量删除功能示例代码
Aug 17 Javascript
详解Vue中watch对象内属性的方法
Feb 01 Javascript
vue中使用微信公众号js-sdk踩坑记录
Mar 29 Javascript
react高阶组件添加和删除props
Apr 26 Javascript
layer.open提交子页面的form和layedit文本编辑内容的方法
Sep 27 Javascript
Vue.js组件通信之自定义事件详解
Oct 19 Javascript
JS实现随机抽取三人
Nov 06 Javascript
Vue实现手机号、验证码登录(60s禁用倒计时)
Dec 19 Vue.js
js实现鼠标拖拽缩放div实例代码
Mar 25 #Javascript
Vue框架下引入ActiveX控件的问题解决
Mar 25 #Javascript
9102了,你还不会移动端真机调试吗
Mar 25 #Javascript
详解原生JS回到顶部
Mar 25 #Javascript
javascript验证form表单数据的案例详解
Mar 25 #Javascript
elementUI select组件默认选中效果实现的方法
Mar 25 #Javascript
详解javascript函数写法大全
Mar 25 #Javascript
You might like
php使用CURL不依赖COOKIEJAR获取COOKIE的方法
2015/06/17 PHP
PHP针对字符串开头和结尾的判断方法
2016/07/11 PHP
老生常谈ThinkPHP中的行为扩展和插件(推荐)
2017/05/05 PHP
php微信公众号开发之欢迎老朋友
2018/10/20 PHP
PHP实现提取多维数组指定一列的方法总结
2019/12/04 PHP
使javascript也能包含文件
2006/10/26 Javascript
帮助避免错误的Javascript陷阱清单
2009/05/31 Javascript
指定位置如果有图片显示图片,无图片显示广告的JS
2010/06/05 Javascript
javascript图片相似度算法实现 js实现直方图和向量算法
2014/01/14 Javascript
jQuery动画效果animate和scrollTop结合使用实例
2014/04/02 Javascript
jQuery toggleClass应用实例(附效果图)
2014/04/06 Javascript
js的延迟执行问题分析
2014/06/23 Javascript
jquery结合CSS使用validate实现漂亮的验证
2015/01/29 Javascript
javascript实现仿腾讯游戏选择
2015/05/14 Javascript
Jquery实现简单的轮播效果(代码管用)
2016/03/14 Javascript
关于Vue实现组件信息的缓存问题
2017/08/23 Javascript
chorme 浏览器记住密码后input黄色背景处理方法(两种)
2017/11/22 Javascript
微信小程序调用摄像头隐藏式拍照功能
2018/08/22 Javascript
微信域名检测接口调用演示步骤(含PHP、Python)
2019/12/08 Javascript
JQuery事件委托(适用于给动态生成的脚本元素添加事件)
2020/02/01 jQuery
element中的$confirm的使用
2020/04/26 Javascript
详解node.js创建一个web服务器(Server)的详细步骤
2021/01/15 Javascript
Python实现的飞速中文网小说下载脚本
2015/04/23 Python
python检查序列seq是否含有aset中项的方法
2015/06/30 Python
Python2.x利用commands模块执行Linux shell命令
2016/03/11 Python
Python的argparse库使用详解
2018/10/09 Python
实例讲解Python中整数的最大值输出
2019/03/17 Python
python sorted方法和列表使用解析
2019/11/18 Python
python base64库给用户名或密码加密的流程
2020/01/02 Python
python 6.7 编写printTable()函数表格打印(完整代码)
2020/03/25 Python
Python中过滤字符串列表的方法
2020/12/22 Python
哈萨克斯坦最大的时装、鞋子和配饰在线商店:Lamoda.kz
2019/11/19 全球购物
用Python匹配HTML tag的时候,<.*>和<.*?>有什么区别
2012/11/04 面试题
资产经营总监岗位职责范文
2013/12/01 职场文书
幼儿园毕业寄语
2014/04/03 职场文书
网吧七夕活动策划方案
2014/08/31 职场文书