美文网首页前端进阶与开发实践Web前端之路让前端飞
翻滚吧,设计模式之03代理模式笔记

翻滚吧,设计模式之03代理模式笔记

作者: 莫闻 | 来源:发表于2017-05-13 19:46 被阅读9次

    代理模式

    • 代理模式是为对象提供一个代用品或者占位符,以便控制对他的访问。
    • 代理模式的关键是,当我们不便直接访问一个对象或不满足需要时,提供一个替身对象来控制对这个对象的访问,
    • 客户实际上是访问的是替身对象。替身对象对请求做出一些处理之后,在把请求转交给本体对象。
    //不使用代理模式
    客户--> 本体
    
    //使用代理模式
    客户-->代理-->本体
    
    • 概念说完了,来看一个栗子
    • 第一个例子——小明追 MM 的故事
      四月一个晴朗的早晨,小明遇见了他的百分百女孩,我们暂且称呼小明的女神为
      A。两天之后,小明决定给 A 送一束花来表白。刚好小明打听到 A 和他有一个共同的朋友 B,于是内向的小明决定让 B 来代替自己完成送花这件事情。
    • 先用代码来描述一下小明追女神的过程,先看看不用代理模式的情况:
    var Folwer = function(){}
    var xiaoming = {
        sendFlower:function(target){
            var flower = new Flower();
            target.receiveFlower(flower);
        }
    }
    var A = {
        receiveFlower:function(flower){
            console.log("收到了" + flower);
        }
    }
    
    xiaoming.sendFlower(A);
    
    • 接下来我们引入代理B,通过代理B给A送花
    var Flower = function(){};
    var xiaomimg = {
        sendFlower:function(target){
            var flower = new Flower();
            target.receiverFlower( flower );
        }
    }
    var B = {
        receiverFlower:function(flower){
            A.receiverFlower( flower );
        }
    }
    var A = {
        receiverFlower:function(flower){
            console.log("收到了" + flower);
        }
    }
    
    xiaoming.sendFlower(B);
    

    至此我们就完成了最简单的一个代理模式
    那么有同学就要问了,小明自己去送和B去送,看起来不是二者没有本质区别,而且还把事情搞复杂了。
    的确,此处的代理模式毫无用处,它所做的只是把请求简单地转交给本体。但不管怎样,我
    们开始引入了代理,这是一个不错的起点。

    • 那么现在我们改变故事的背景设定,假设当 A 在心情好的时候收到花,小明表白成功的几率有60%,而当 A 在心情差的时候收到花,小明表白的成功率无限趋近于 0。小明跟 A 刚刚认识两天,还无法辨别 A 什么时候心情好。如果不合时宜地把花送给 A,花被直接扔掉的可能性很大,这束花可是小明吃了 7 天泡面换来的。但是 A 的朋友 B 却很了解 A,所以小明只管把花交给 B, B 会监听 A 的心情变化,然后选择 A 心情好的时候把花转交给 A这么看下来是不是就感觉好多了
    var Flower = function(){};
    var xiaoming = {
        sendFlower:function(target){
            var flower = new Flower();
            target.receiveFlower(flower);
        }
    }
    var B = {
        receiveFlower:function(flower){
            A.listenGoodMood(function(){//监听A的心情
                A.reveiveFlower(flower);
            });
        };
    }
    var A = {
        receiveFlower:function(flower){
            console.log("收到了" + flower);
        },
        listenGoodMood:function(fn){
            setTimeout(function(){//假设A的心情10秒后变好
                fn();
            },10000);
        }
    }
    xiaoming.sendFlower(B);
    

    这个就是一个完整的代理模式的例子了。

    • 代理模式有代理保护和虚拟代理,缓存代理等
      比如代理B可以帮A过滤掉一些没有宝马或者年龄过大的人,这种请求在B处就会被处理掉,这种就叫做代理保护。
      这样A可以保持良好的女神形象不直接拒绝任何人,却又不会导致太多其他骚扰。
      而虚拟代理是js最常用的一种代理模式。
    • 下面来看一个实际中开发的例子
      虚拟代理实现图片的预加载,常见的做法是:先用一张loading图片占据位置,然后异步的方式加载图片,等加载后再填充到img标签中。
      这种场合就很适合虚拟代理。我们把网速调至 5KB/s,然后通过 MyImage.setSrc 给该 img 节点设置 src,可以看到,在图片
      被加载好之前,页面中有一段长长的空白时间。
    var myImg = (function(){
        var imgEle = document.createElement("img");
        document.body.appendChild(imgEle);
        return {
            setSrc:function(src){
                imgEle.src = src;
            }
        }
    })();
    
    

    现在开始引入代理对象 proxyImage,通过这个代理对象,在图片被真正加载好之前,页面中
    将出现一张占位的菊花图 loading.gif, 来提示用户图片正在加载。代码如下:

    var proxyImage = (function(){
        var img = new Img();
        img.onload = function(){//加载完毕后,设置为需要加载的图片地址
            myImage.setSrc(this.src);
        }
        return {
            setSrc:function(src){//在刚进入页面时,先将图片地址设置为loading
                myImage.setSrc("loading.gif");
                img.src =src;//然后将src赋值给新创建的img,作为一个中转缓存点
            }
        }
    })();
    
    proxyImage.setSrc("http://www.baidu.com/img");
    //现在我们通过proxyImage间接访问myImage。proxyImage控制了客户对myImage的访问,并在此过程中添加了其他额外的操作,比如在真正的图片加载好后,先调用一张loading图。
    

    缓存代理的例子---计算乘积

    var mult = function(){
        console.log("开始计算乘积");
        for(var i = 0, len = arguments.length; i < len; i++){
            a = a * arguments[i];
        }
        return a;
    }
    
    var proxyMult = (function(){
        var cache = {};//缓存
        return function(){
            var arg = Array.prototype.join.call(arguments, ",");
            if(arg in cache){
                return cache[arg];
            }
            return cache[arg] = mult.apply(this, arguments);
        }
    })();
    

    ---《javascript设计模式与开发实践》

    相关文章

      网友评论

        本文标题:翻滚吧,设计模式之03代理模式笔记

        本文链接:https://www.haomeiwen.com/subject/lhffxxtx.html