微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JavaScript设计模式之代理模式详解

代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子。但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处。在我看来,代理模式最大的好处,就是在不动原有对象的同时,可以给原有对象增加一些新的特性或者行为。

rush:js;"> /** * pre:代理模式 * 小明追求A,B是A的好朋友,小明比较腼腆,不好意思直接将花交给A, * 于是小明将花交给B,再由B交给A. */ //----------- 示例1 --------- // 不使用代理 var Flower = function() {}; var xiaoming = { sendFlower: function(target) { var flower = new Flower(); target.receiveFlower(flower); } }; var A = { receiveFlower: function(flower) { console.log("收到花:" + flower); } }; xiaoming.sendFlower(A);

// ----------- 示例2 --------------
// 使用代理1
var Flower = function() {};
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower();
B.receiveFlower(flower);
}
};
var B = {
receiveFlower: function(flower) {
A.receiveFlower(flower);
}
};
var A = {
receiveFlower: function(flower) {
console.log("收到花:" + flower);
}
};
xiaoming.sendFlower(B);

//------------- 示例3 ---------------
/*

  • 使用代理2
  • 从示例1和示例2,看不出使用代理有什么用处,B只不过是从中间转手了一次。
  • 接下来,我们想一下。给喜欢的人送花,怎样才能提高成功率呢?
  • 我们都知道,人有心情好和心情差的时候,当美女心情好的时候,送花成功的概率自然要大些。
  • 于是,我们将代理升级,监听美女的心情,心情好的时候再给她送花。
  • 为了演示,我们假设2秒后,A的心情变好。
    */

var Flower = function() {};
var xiaoming = {
sendFlower: function(target) {
var flower = new Flower();
B.receiveFlower(flower);
}
};
var B = {
receiveFlower: function(flower) {
A.listenGoodMood(function() {
A.receiveFlower(flower);
});
}
};
var A = {
receiveFlower: function(flower) {
console.log("收到花:" + flower);
},listenGoodMood: function(fn) {
setTimeout(function() {
fn.apply(this,arguments);
},2000);
}
};
xiaoming.sendFlower(B);
// ---------- 示例4 ---------------
/*

  • 【代理模式用处】:虚拟代理
  • 这里以加载图片为例,我们都知道当网络不畅以及图片过大时,图片加载都比较慢,
  • 为了更好的用户体验,我们都会在原图片未加载完成前,加上loading图片
  • /
    //--4 _01未使用代理--
    var myImage = (function() {
    var imgNode = document.createElement("img");
    document.body.appendChild(imgNode);
    return {
    setSrc: function(src) {
    this.imgNode.src = src;
    }
    }
    })();
    myImage.setSrc("xxx");
    //--4_02使用代理--
    var proxyMyImage = (function() {
    var img = new Image();
    img.onload = function() {
    myImage.setSrc(this.src);
    };
    return {
    setSrc: function(src) {
    myImage.setSrc("loading.jpg");
    img.src = src;
    }
    }
    })();
    proxyMyImage.setSrc("xxx");
    /
  • [注]:这里可以看到代理模式的好处:在不改变原有接口的同时,可以为系统添加新的行为。
    /
    //--------- 示例5---------------
    /
  • 【代理模式用处】:合并http请求
  • 这里以选择文件同步为例。
  • 以往用户同步文件,在用户选中的时候就触发,这种方法做到了实时性,但无疑增加了网络的开销。
  • 实际在使用的过程中,往往并不需要立刻就同步。
  • 以下通过代理模式,将在用户选中文件2秒后进行同步请求。
  • */
    // --- 包含一段HTML代码,请自行添加一个文件中 ------ Box" id="1">1 Box" id="2">2 Box" id="3">3 Box" id="4">4 Box" id="5">5 Box" id="6">6 Box" id="7">7 Box" id="8">8 Box" id="9">9 // -- 上传文件 -- var synchronizefile = function(id) { console.log("开始同步文件:" + id); }; var proxySynchronizefiles = (function() { var fileCache = [],timer; return function(id) { fileCache.push(id); if(timer) { return; } timer = setTimeout(function() { synchronizefile(fileCache.join(",")); clearTimeout(timer); timer = null; checkArr.length = 0; },2000); } })(); var checkArr = document.getElementsByTagName("input"); for(var i = 0,c; c = checkArr[i++];) { c.onclick = function() { if(this.checked == true) { proxySynchronizefiles(this.id); } } } // ------------ 示例6 ----------------- /*
  • 【代理模式用处】:缓存代理
  • 以计算器为例,比如计算某些数的乘积,当参数重复时,我们希望不用重复计算,直接返回结果。
  • 以下用到代理模式做缓存。
    /
    var mult = function() {
    if(!arguments) {
    console.log("请输入参数");
    return;
    }
    var a = 1;
    for(var i = 0,b; b = arguments[i++];) {
    a = a
    b;
    }
    return a;
    };

var proxyMult = (function() {
var cache = {};
return function() {
var str = Array.prototype.join.call(arguments,",");
if(str in cache) {
console.log("重复return.");
return cache[str];
}
return cache[str] = mult.apply(this,arguments);
}
})();

console.log(proxyMult(2,3,4));
console.log(proxyMult(2,4));
//------------ 示例7 --------------
/*

  • 缓存代理升级 - 通用版计算
  • /
    var mult = function() {
    if(!arguments) {
    return;
    }
    var t = 1;
    for(var i = 0,a; a = arguments[i++];) {
    t = t
    a;
    }
    return t;
    };
    var plus = function() {
    if(!arguments) {
    return;
    }
    var t = 0;
    for(var a of arguments) {
    t += a;
    }
    return t;
    };
    var createProxyCaculate = function(fn) {
    var cache = {};
    return function() {
    var str = Array.prototype.join.call(arguments,");
    if(str in cache) {
    console.log("重复return" + str);
    return cache[str];
    }
    return cache[str] = fn.apply(this,arguments);
    }
    };
    var proxyMult = createProxyCaculate(mult);
    var proxyPlus = createProxyCaculate(plus);
    console.log(proxyMult(2,4));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐