美文网首页前端进阶与开发实践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