js设计模式-代理模式

165 阅读2分钟

定义

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

条件

代理模式中需要保持代理和本体接口的一致性,这样做我们有两个好处:

  • 用户可以放心地请求代理,他只关心是否能得到想要的结果。
  • 在任何使用本体的地方都可以替换成使用代理。

代理实例

虚拟代理实现图片预加载
<template>
    <img ref="imgNode" src="" alt="" srcset="">
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue'
import imgsrc from '../assets/logo.png'
export default defineComponent({
  setup() {
    const imgNode = ref(null);
    onMounted(() => {
      // 本体对象
      const myImage = (src) => {
        imgNode.value.src = src;
      }
      // 代理对象
      const proxyImg = (() => {
        const img = new Image;
        img.onload = function(){
          myImage(this.src)
        }
        return function(src){
          myImage(imgsrc)
          img.src= src;
        }
      })()
      proxyImg('https://www.cnblogs.com/images/logo.svg?v=R9M0WmLAIPVydmdzE2keuvnjl-bPR7_35oHqtiBzGsM')
      // 不需要预加载效果可直接替换
      // myImage('https://www.cnblogs.com/images/logo.svg?v=R9M0WmLAIPVydmdzE2keuvnjl-bPR7_35oHqtiBzGsM')
    })
    return {
      imgNode,
    }
  },
})
</script>
虚拟代理合并http请求
<template>
    <input type="checkbox" id="1" @click="clickHandle('1', $event)">1
    <input type="checkbox" id="2" @click="clickHandle('2', $event)">2
    <input type="checkbox" id="3" @click="clickHandle('3', $event)">3
    <input type="checkbox" id="4" @click="clickHandle('4', $event)">4
    <input type="checkbox" id="5" @click="clickHandle('5', $event)">5
    <input type="checkbox" id="6" @click="clickHandle('6', $event)">6
    <input type="checkbox" id="7" @click="clickHandle('7', $event)">7
    <input type="checkbox" id="8" @click="clickHandle('8', $event)">8
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  methods: {
    synFile(id) {
      console.log('同步'+id)
    },
    proxySynFile: (function() {
      const cache = [];
      let timer = null;
      return function(id){
        cache.push(id);
        if (timer) return;
        timer = setTimeout(() => {
          this.synFile(cache.join(','))
          clearTimeout(timer)
          timer = null
          cache.length = 0
        }, 2000)
      }
    })(),
    clickHandle(id, e) {
      if (e.target.checked) this.proxySynFile(id)
    }
  }
})
</script>
缓存代理
const mult = function() {
  console.log(arguments)
  let a = 1;
  for (let i = 0; i < arguments.length; i++) {
    a = a * arguments[i];
  }
  return a;
}
const plus = function() {
  let a = 0;
  for (let i = 0; i < arguments.length; i++) {
    a = a + arguments[i];
  }
  return a;
}
const proxyFunc = function(fn) {
  const cache = {};
  return function() {
    const args = Array.prototype.join.call(arguments, ',')
    if (args in cache) {
      return cache[args]
    }
    console.log(arguments)
    return cache[args] = fn.apply(this, arguments)
  }
}
const proxyMult = proxyFunc(mult)
const proxyPlus = proxyFunc(plus)
console.log(proxyMult(1, 2, 3, 4))
console.log(proxyPlus(1, 2, 3, 4))

其他代理模式

  • 防火墙代理:控制网络资源的访问,保护主题不让“坏人”接近。
  • 远程代理:为一个对象在不同的地址空间提供局部代表,在Java中,远程代理可以是另一个虚拟机中的对象。
  • 保护代理:用于对象应该有不同访问权限的情况。
  • 智能引用代理:取代了简单的指针,它在访问对象时执行一些附加操作,比如计算一个对象被引用的次数。
  • 写时复制代理:通常用于复制一个庞大对象的情况。写时复制代理延迟了复制的过程,当对象被真正修改时,才对它进行复制操作。写时复制代理是虚拟代理的一种变体,DLL(操作系统中的动态链接库)是其典型运用场景。