zoukankan      html  css  js  c++  java
  • js设计模式——代理模式

    代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问。

    关键:当客户不方便直接访问一个对象或者不满足需求的时候,提供一个替身对象来控制这个对象的访问。客户实际上访问的是替身对象。替身对象对请求作出一些请求之后,再把请求交给本体对象。

    保护代理用于控制不同权限的对象对目标对象的访问,但在 JavaScript 并不容易实现保护代理,因为我们无法判断谁访问了某个对象。
    而虚拟代理是最常用的一种代理模式。
    下面是一个图片预加载的代码,这里的代理起到了占位的作用。
     
    <!DOCTYPE html>
    <html>
    <head>
     <title>图片预加载</title>
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
     var myImage=(function () {
      // body...
      var imgNode=document.createElement('img');
      document.body.appendChild(imgNode);
      console.log(3)
      return {
       setSrc:function(src){
        console.log(4)
        imgNode.src=src;
       }
      }
     })();
    
     var proxyImage=(function(){
      var img=new Image;
      img.onload=function(){
       console.log(this.src)
       myImage.setSrc(this.src);
      }
      console.log(1)
      return {
       setSrc:function(src){
        console.log(2)
        myImage.setSrc('./loading.jpg');
        img.src=src;
       }
      }
     })();
    
     proxyImage.setSrc("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=716310665,173562528&fm=26&gp=0.jpg");
    </script>
    </html>
     
    图片预加载为什么要使用代理呢,是因为要遵循单一职责原则。
     
    单一职责原则指的是,就一个类(通常也包括对象和函数等)而言,应该仅有一个引起它变化的原因。如果一个对象承担了多项职责,就意味着这个对象将变得巨大,引起它变化的原因可能会有多个。面向对象设计鼓励将行为分布到细粒度的对象之中,如果一个对象承担的职责过多,等于把这些职责耦合到了一起,这种耦合会导致脆弱和低内聚的设计。当变化发生时,设计可能会遭到意外的破坏。
     
     
    代理和本体接口一致性。加载图片的myImage和proxyImage都使用的是setSrc接口。这样做有两个好处:
     用户可以放心地请求代理,他只关心是否能得到想要的结果。
     在任何使用本体的地方都可以替换成使用代理。 
     
    下面是代理模式下的求乘积,也是一个动态创建代理的例子
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>代理模式-求乘积</title>
      </head>
      <body></body>
      <script>
        //计算乘积的函数
        var mult = function () {
          console.log("开始计算乘积");
          var a = 1;
          for (let i = 0; i < arguments.length; i++) {
            a = a * arguments[i];
          }
          return a;
        };
    
        var plus = function () {
          var a = 0;
          console.log("开始计算加法");
          for (var i = 0, l = arguments.length; i < l; i++) {
            a = a + arguments[i];
          }
          return a;
        };
    
        var proxyMult = (function () {
          var cache = {};
          return function () {
            var args = Array.prototype.join.call(arguments, ",");
            if (args in cache) {
              return cache[args];
            }
            return (cache[args] = mult.apply(this, arguments));
          };
        })();
    
        var createProxyFactory = function (fn) {
          var cache = {};
          return function () {
            var args = Array.prototype.join(arguments, ",");
            if (args in cache) {
              return cache[args];
            }
            return (cache[args] = fn.apply(this, arguments));
          };
        };
    
        var proxyPlus = createProxyFactory(plus);
    
        console.log(proxyMult(1, 2, 3, 4));
        console.log(proxyMult(1, 2, 3, 4));
        console.log(proxyPlus(1, 2, 3, 4));
        console.log(proxyPlus(1, 2, 3, 4));
      </script>
    </html>
     
     
     
  • 相关阅读:
    3个同一行div的摆放div
    Android 项目开发
    iOS 8
    iOS 8
    __FILE__ 与 $_SERVER['SCRIPT_FILENAME']的区别
    高德百度坐标系转换方法
    高德百度坐标系转换方法
    在iOS开发中使用icon font的方法
    在iOS开发中使用icon font的方法
    UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释
  • 原文地址:https://www.cnblogs.com/ellen-mylife/p/13680845.html
Copyright © 2011-2022 走看看