什么是代理模式
代理模式是一个非常常见的模式,在我们日常生活中,有很多例子,比如VPN工具,明星的经纪人等都是代理。但是,有些人就会想了,明明可以直接访问对象,为什么还要在外面加一层壳呢?这里也就讲到了代理的好处了,在我看来,代理模式最大的好处就是,在不动用原有对象的情况下,可以给原有对象添加一些新特性和行为 我们举一个日常生活中很简单的例子,小明想租房
1.小明自己去找房子
//定义一个房子类
var House = function(houseType){
this.houseType = houseType
}
House.prototype.getHouseType = function(){
return this.houseType
}
//定义一个用户对象
var user = {
findHouse:function(house){
consloe.log('租到了一间' + house.getHouseType())
}
}
//租到了一间精品房
user.findHouse(new House('精品房'))
复制代码
当然了,现在租房一般都是网上找中介,或者找租房平台
2.小明找租房平台租房
//定义一个房子类
var House = function(houseType){
this.houseType = houseType
}
House.prototype.getHouseType = function(){
return this.houseType
}
//定义一个租房平台对象
var RentalPlatform = {
findHouse:function(house) {
user.findHouse(Hose.getHouseType())
}
}
//定义一个用户对象
var user = {
findHouse:function(house){
consloe.log('租到了一间' + house.getHouseType())
}
}
//租到了一间精品房
user.findHouse(new House('精品房'))
复制代码
代理是不是看起来很简单,但是这时候也有人会有疑问了,使用代理和不使用代理,它们实现的结果不都是一样的吗,这是肯定的,结果必须要是一样的,但是使用代理,并不是把一件简单的事情变得复杂化了,代理的使用场景当然不是这种简单的场景,而是针对一些比较复杂或特殊的情况使用,这里只是为了举例说明代理的实现。下面就介绍一些使用场景。
代理使用场景
普通代理模式
我们继续讨论上面租房的问题,在生活中,我们会常常遇到租房公司再给你找房时,而你属于工作时间,由于挣钱的同时需要找房,所以才会去找代理。就像到了过年的时候,很多人会因为自己抢不到票而找抢票平台帮你抢票,就好比现在的一些代购一样,自己不能出国而去找能出国的人给你代购东西一样,租房平台一些线下店都有他们的营业时间,我们拿正常的上下班时间来举个例子(09:00-18:00)。
//定义一个房子类
var House = function(houseType){
this.houseType = houseType
}
House.prototype.getHouseType = function(){
return this.houseType
}
//添加一个条件 判断线下店是否开门营业了
House.prototype.business = function() {
var curTime = new Date().getHours();
return curTime >= 9 && curTime <= 18 ? that.getHouseType() : '"非营业时间!"';
}
//定义一个租房平台对象
var RentalPlatform = {
findHouse:function(house) {
user.findHouse(Hose.getHouseType())
}
}
//定义一个用户对象
var user = {
findHouse:function(house){
consloe.log('租到了一间' + house.getHouseType())
}
}
//租到了一间精品房
user.findHouse(new House('精品房'))
复制代码
虚拟代理模式
在日常开发中,常见的虚拟代理主要有图片预加载 图片预加载是一种常见的前端函数,在图片过大或者网络不畅通的时候,我们一般不会直接给img标签节点设置src属性,而是使用一张loading图片作为占位符,然后在用异步的方式加载图片,等到图片加载完毕后,再把它填充到img标签里,直接上代码。
var perImg = function() {
var image = document.createElement('img')
document.body.appendChild(image)
var img = new Image
img.onload = function() {
image.src = img.src;
}
return {
setSrc: function(src) {
image.src = '../loading.gif';
img.src = src;
}
}
})()
perImg.setSrc("https://ss0.baidu.com/73t1bjeh1BF3odCf/it/u=2894591933,850614106&fm=85&s=98B6F3B21A413F4B5E16CE55030090FB")
复制代码
上面就是图片预加载实现的过程了,想要体现一段代码是否优秀,往往要看你的代码是否易于维护,特别是对大量的代码,首先看上面代码有几个问题:
- 1.代码不符合单一原则,我们把负责图片预加载的处理和img处理写在了一个函数内,
- 2.如果以后网速特别好,比如5G时代,那么加载图片就不用使用预加载了,这个功能也就可以去掉了
针对以上问题,我们可以使用代理来解决
var myImage = (function() {
var images = document.createElement('img');
document.body.appendChild(images);
return {
setSrc: function(src) {
imgNode.src = src;
}
}
})();
var preImage = (function() {
var img = new Image;
img.onload = function() {
myImage.setSrc = img.src;
};
return {
setSrc: function(src) {
myImage.setSrc( '../loading.gif');
img.src = src;
}
}
})();
perImg.setSrc("https://ss0.baidu.com/73t1bjeh1BF3odCf/it/u=2894591933,850614106&fm=85&s=98B6F3B21A413F4B5E16CE55030090FB")
复制代码
这样,我们把图片预加载和img标签分开写,有利于维护
缓存代理
缓存代理是代理模式中最常见的一种代理,它可以为一些开销大的运算结果提供暂时的储存,在下次运算时,如果带进来的参数一致,则可以直接返回之前运算结果,大大的提高效率和省开销,现在我们通过一个简单的实例来理解一下缓存代理
var mult = function(){
console.log('开始计算乘法')
var number = 1
length = arguments.length //若干个数的长度
for(var i = 0,i < length;i++){
number = number*arguments[i];
}
retuan number
}
var proxyMult = (function(){
var cache = {}; //用来储存运算结果写入缓存
return function(){
var args = Array.prototype.join.call( arguments, ',') // 将
arguments元素添加到args数组,与逗号隔开
//如果缓存中存在
if(args in cache){
return cache[args]; //直接返回
}
//不存在
return cache[args] = mult.apply( this, arguments)
}
proxyMult( 1,2,3,4) //输出1*2*3*4的值
复制代码
通过缓存代理模式,可将决定权交给代理函数对象proxyMult,而mult函数可以专注于自身的职责。
总结
当然,代理还有其他的分类代理,比如,智能代理,远程代理。但是在JavaScript中我们使用最多,也最常见的就是虚拟代理和缓存代理。