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

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

    代理模式的关建是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际访问的是替身对象,替身对象对请求做出一些处理后,再把请求转交给本体对象。

    先来看一个例子,假设A想送花给C,但又不知道C的心情,C的心情好时即送花成功,那么可以通过C的好朋友B来送花,B了解C,可以知道C的心情。

    var Flower = function(){};
         //A发起送花请求
         var A = {
          sendFlower:function(target){
            var flower = new Flower();
             target.receiveFlower(flower);
          }
         };
         //B接受送花请求 并监听到C的心情好时转给C
         var B = {
             receiveFlower:function(flower){
               C.listenGoodMood(function(){
                 C.receiveFlower(flower);
              });
             }
         };
         //C接受送花请求 和 发表心情
         var C = {
             receiveFlower :function(flower){
                console.log(flower);
             },
             listenGoodMood:function(fn){
               setTimeout(function(){
                  fn();
               },1000)
             }
         };
    
         A.sendFlower(B);

    在实际开发中,由于花的价格昂贵,那么可以当B监听到C的好心情时,才创建花来节省消耗。

    var B = {
             receiveFlower:function(){
               C.listenGoodMood(function(){
                var  flower = new Flower();
                 C.receiveFlower(flower);
              });
             }
         };

    在这个例子中,最关键的就是B对象,也就是该章描述的代理对象,代理B可以帮助C过滤掉那些年龄太大之类的人,这些请求可以被B直接拒绝掉,这种被称为保护代理。而在真正需要的时候才来创建对象,也就是在C心情好的时候才创建花,被称为虚拟代理。

    下面来看一个实际开发中的例子,通常在加载一个比较大的图片时,我们会先用一张菊花图提示用户化正在加载,当真正的图片被加载完成后,才显示该图片。

    //加载图片的类
           var myImg = (function(){
               var imgNode = document.createElement('img');
               document.body.appendChild(imgNode);
               return {
                  setSrc:function(src){
                     imgNode.src = src;
                  }
               }
           })();
           //代理类,在图片加载完成之前 显示菊花图 加载完成后 改换真正的图片
           var proxyImg = (function(){
              var img = new Image();
              img.onload = function(){
                 myImg.setSrc(this.src);
              };
              return {
                 setSrc:function(src){
                    myImg.setSrc("菊花图!");
                    img.src = src;
                 }
              }
           })();
    
           proxyImg.setSrc('真正的图片!');

    在这里,也许会有疑问,即使不用代理模式也能实现这种效果,先来看一下不用代理的代码实现:

    var myImg = (function(){
               var imgNode = document.createElement('img');
               document.body.appendChild(imgNode);
               var img = new Image();
               img.onload = function(){
                 myImg.setSrc(this.src);
               };
               return {
                  setSrc:function(src){
                     myImg.setSrc("菊花图!");
                     img.src = src;
                  }
               }
           })();
    
           myImg.setSrc("真正的图片!")

    为了说明代理的意义,先引入一个概念,即单一职责原则,表示一个类应该只有一个引起它变化的原因。这保证了类的高内聚和低耦合。

    在不使用代理的例子下,myImg负责了给img设置src之外,还要负责预加载的图片,有时候我们的图片可能很小,或者以后的网速很快,那么我们就需要深入到该类来删除预加载的功能。

    而如果采用了代理模式,那么当我们不需要预加载时,只需要直接调用myImg就可以了。

     

    虚拟代理在惰性加载中的应用。

    如一个控制台,当用户输入console.log(0)时,会在控制台打印0,但通常用户并不会一开始就打开控制台,所以也不会一开始就加载控制台。那么我们可以先创建一个代理类,将要打印的信息放进该代理类,当用户按下F12打开控制台的时候,我们创建了控制台之后,再遍历这些信息并输出。

     

    代理在zepto类库事件处理中使用得比较多,具体可以参考zepto事件分析系列,其中带有proxy的即为代理对象。

     

    参考自Javascript设计模式与开发实践一书。

  • 相关阅读:
    委托返回类型的协变性
    委托参数的逆变性
    单例采用双锁定技术
    Jupyter Notebook 工作空间 / 默认路径 的设置方式
    Runaway argument错误 [Overleaf: 在线Latex] [Type 3问题后续]
    [Android ADB] An auto-input method for Android and Windows
    [Latex] 所有字体embedded: Type3 PDF文档处理 / True Type转换为Type 1
    螺旋矩陣 非数组解法
    2014.9.11 Research Meeting Report
    2014.8.23 Research Meeting Report
  • 原文地址:https://www.cnblogs.com/Darlietoothpaste/p/6681141.html
Copyright © 2011-2022 走看看