设计模式-代理模式

代理模式

代理模式是对对象的代理,提供访问对象的权利,不直接访问对象,而是通过代理对象访问。代理分为保护代理和虚拟代理。保护代理就是为对象提供过滤机制。在Javascript中其实可以使用原生的Proxy实现。虚拟代理是将一些大的开销交给代理,达到惰性加载的目的。保护代理在Javascript不常见,着重记录虚拟代理

虚拟代理

虚拟代理就是将一些大的开销交给代理处理的过程。用常用的预加载技术举例,以下是没有使用代理的形式

const createImg = (function(){
  const imgNode = document.createElement();
  document.appendChild(imgNode);
  return {
    setSrc(src){
      imgNode.src = src;
    }
  }
})()

接下来引入代理对象

const createImg = (function(){
  const imgNode = document.createElement('img');
  document.appendChild(imgNode);
  return {
    setSrc(src){
      imgNode.src = src;
    }
  }
})()
// 将不变与变化分离开
const proxyCreateImg = function(){
  const img = new Image();
  img.onload = function(){
    // 加载完毕后将请求极爱还给createImg
    createImg.setSrc(this.src);
  }
  return {
    setSrc(src){
      createImg.setSrc('loading.img');
      img.src = src;
    }
  }
}

添加代理对象对createImg进行代理,当图片加载完全将请求交还给createImg,在代理中进行消耗比较大的图片请求过程和loading。

为什么要使用代理对象

上述例子本身我们不使用代理对象也可以实现相同的效果

const createImg = (function(){
  const imgNode = document.createElement('img');
  document.body.appendChild(imgNode);
  const img = new Image;
  img.onload = function(){
    imgNode.src = this.src;
  }
  return {
    setSrc(src){
      imgNode.src = 'loading.jpg';
      img.src = src;
    }
  }
})()

如上。那为什么还要使用代理对象呢?在设计模式中需要时时刻刻注意那几条原则,不变与变化分离,开放-封闭原则、单一职责原则。。。假设以后我们不需要预加载了,那我们势必要深入代码内部,重新修改实现,代码中预加载部分与创建节点部分耦合,有两处变化的地方。但是使用代理对象可以做到分离的目的。如果做到接口一致,以后我们不需要使用预加载的时候就不使用,并不会有什么影响

缓存代理

某些重复的计算可以使用缓存代理的形式保存,下次获取时不进行重复的计算,假设有如下求和过程

function computedCount(){
  let count = 0;
  for(let i=0;i<arguments.length;i++){
    count+=arguments[i];
  }
  return count;
}
const proxyComputedCount = (function(){
  const caches = Object.create(null);
  return function(){
    const cache = Array.prototype.join.call(arguments,',');
    if(cache in caches){
      return caches[cache];
    }
    return caches[cache] = computedCount.apply(this,arguments);
  }
})()
console.log(proxyComputedCount(1,2,3,4))

代理模式在ajax中的应用

缓存代理可以用于在重复的操作中,所以ajax同样道理,只是由于ajax异步的原因,需要在异步中获取

const axios = require('axios')
function getArticle(id,callback){
  console.log('进来')
  return axios.get(`http://jsonplaceholder.typicode.com/comments?postId=${id}`)
  .then(results=>Promise.resolve(results.data));
}
const proxyGetArticle = (function(){
  const caches = {};
  return async function(id){
    const cache = Array.prototype.join.call(arguments,',');
    // console.log(caches)
    if(cache in caches){
      console.log('在里边')
      return caches[cache];
    }
    await 
      getArticle(id).then(res=>{
        console.log('获取')
        Promise.resolve(caches[cache] = res)
      })
    // await 
    return caches[cache];
  }
})()
async function  getData(){
  const start = Date.now()
  const data= await  proxyGetArticle(1)
  const end = Date.now()
  console.log(end-start)
  const data1 = await proxyGetArticle(1)
  console.log(Date.now()-end)
}

getData()

/*
进来
获取
2325
在里边
5
*/

何时使用代理

虽然使用代理模式非常方便,但是不需要时刻想着某个问题是否需要代理模式,当真正碰到不方便的时候,我们能马上想到这个方法。代理模式有非常多的情况,但是考虑到JavaScript的适用性,在JavaScript中使用最多的是虚拟代理和缓存代理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值