javaScript设计模式——代理模式(五)

设计模式:有助于提高代码的复用性和可维护性

代理模式为一个对象提供一个代用品或占位符,以便控制它的访问。
当我们不方便直接访问某个对象时,或不满足需求时,可考虑使用一个替身对象来控制该对象的访问。替身对象可对请求预先进行处理,再决定是否转交给本体对象

用生活中的例子简单的描述一下

1、你自己不太方便买一件商品,可以通过找代购帮你买,然后代购买好东西后交给你。
2、租房或者买房,我们通常会找中介,中介按照我们的需求,帮我们选好几套房子,然后我们在进行对比,最后租到或者买到自己心仪的房子

像这种代购,中介,都可以称之为代理

特点
  • 代理对象可预先处理请求,再决定是否转交给本体;
  • 代理和本体对外显示接口保持一致性
  • 代理对象仅对本体做一次包装
模式细分
  • 虚拟代理(将开销大的运算延迟到需要时执行)
  • 缓存代理(为开销大的运算结果提供缓存)
  • 防火墙代理(控制网络资源的访问)
  • 远程代理(为一个对象在不同的地址控件提供局部代表)
适用场景
虚拟代理:
  • 图片预加载(loading 图)
  • 合并HTTP请求(数据上报汇总)
缓存代理:(前提本体是纯函数)
  • 缓存异步请求数据
  • 缓存较复杂的运算结果
ES6 的 Proxy
  • 实现对象私有属性
  • 实现表单验证
优点

1、可拦截和监听外部对本体对象的访问;
2、复杂运算前可以进行校验或资源管理;
3、对象职能粒度细分,函数功能复杂度降低,符合 “单一职责原则”;
4、依托代理,可额外添加扩展功能,而不修改本体对象,符合 “开发-封闭原则”

缺点

1、额外代理对象的创建,增加部分内存开销;
2、处理请求速度可能有差别,非直接访问存在开销,但 “虚拟代理” 及 “缓存代理” 均能提升性能

代码实现

虚拟代理(延迟执行)
虚拟代理的目的,是将开销大的运算延迟到需要时再执行
模拟场景:图片懒加载

       myImage = (function(){
            var imgDom = document.createElement('img')
            document.body.appendChild(imgDom)
            return {
                setSrc:function(src){
                    imgDom.src = src
                }
            }
        })()
        myImage.setSrc('图片路径')

        //引入代理
        myImage = (function(){
            var imgDom = document.createElement('img')
            document.body.appendChild(imgDom)
            return {
                setSrc:function(src){
                    imgDom.src = src   //图片加载完设置真实图片src
                }
            }
        })()

        proxyMyImage = (function(){
            var img = new Image()
            img.onload = function(){
                myImage.setSrc(this.src);
            }
            return {
                setSrc:function(src){
                    myImage.setSrc('./loading.gif') //预先设置图片src为loading图
                    img.src = src
                }
            }
        })()

模拟场景:http请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
    <input type="checkbox" id="1"></input>1
    <input type="checkbox" id="2"></input>2
    <input type="checkbox" id="3"></input>3
    <input type="checkbox" id="4"></input>4
    <input type="checkbox" id="5"></input>5
    <input type="checkbox" id="6"></input>6
    <input type="checkbox" id="7"></input>7
    <script>
        var synchronousFiles = function(id){
            console.log('开始同步文件,id为:'+id)
        }

        var proxySynchronousFiles = (function(){
            var cache = [] //保存一段时间内要缓存的id
            var timer;
            return function(id){
                cache.push(id)
                if(timer){
                    return;
                }
                timer = setTimeout(()=>{
                    var ids = cache.join(',') 
                    synchronousFiles(ids) //2秒后向本体发送需要同步的id
                    clearTimeout(timer) //清除定时器
                    timer = null
                    cache = [] //清空数组
                },2000)
            }
        })()

        var checkbox = document.getElementsByTagName('input')
        for(var i=0;i<checkbox.length;i++){
            checkbox[i].onclick = function(){
                if(this.checked == true){
                    proxySynchronousFiles(this.id)
                }
            }
        }
    </script>
</body>
</html>

代理缓存
缓存代理的目的,是为一些开销大的运算结果提供暂时存储,以便下次调用时,参数与结果不变情况下,从缓存返回结果,而不是重新进行本体运算,减少本体调用次数。
模拟场景:求阶乘和

		var cache = {}
        function multi(n){
            if(n<1){
                return;
            }
            if(n==1){
                return 1;
            }
            return n * (cache[n-1] || multi(n - 1)); 
        }
        var sum = (function(){
            var result = 0
            return function(n){
                for(var i=1;i<=n;i++){
                    let ret = multi(i)
                    cache[i] = ret 
                    result += ret
                }
                return result;
            }
        })()
        console.log(sum(3))
常用的12种设计模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值