zoukankan      html  css  js  c++  java
  • JS 设计模式六 -- 代理模式

    概念

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

    当客户不方便直接访问一个对象的时候,需要提供一个替身对象来控制对这个对象的访问。

    替身对象对请求做出一些处理之后, 再把请求转交给本体对象。

    实现

    代理模式共有三种:保护代理、虚拟代理、缓存代理

    保护代理:

    用于控制不同权限的对象对目标权限的访问,实现访问访问主题的控制行为。

    // 主体,发送消息
    function sendMsg(msg) {
        console.log(msg);
    }
    
    // 代理,对消息进行过滤
    function proxySendMsg(msg) {
        // 无消息则直接返回
        if (typeof msg === 'undefined') {
            console.log('No Msg');
            return;
        }
        
        // 有消息则进行过滤
        msg = "收到的msg是:" + msg;
    
        sendMsg(msg);
    }
    
    
    sendMsg("msg1"); // msg1
    proxySendMsg('msg2'); // 收到的msg是:msg2
    proxySendMsg(); // No Msg

    虚拟代理

    虚拟代理 用于控制对创建开销很大的本体访问,它会把本体的实例化推迟到有方法被调用的时候,是最常用的一种代理。

    使用虚拟代理来实现图片预加载

    var myImage = (function(){
        var imgNode = document.createElement("img");
        document.body.appendChild(imgNode);
        return {
            setSrc: function(src) {
                imgNode.src = src;
            }
        }
    })();
    // 代理模式
    var ProxyImage = (function(){
        var img = new Image();
        img.onload = function(){
            myImage.setSrc(this.src);
        };
        return {
            setSrc: function(src) {                    
                myImage.setSrc("http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif");
                img.src = src;
            }
        }
    })();
    // 调用方式
    ProxyImage.setSrc("https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png");

    使用虚拟代理实现函数防抖

    // 函数防抖,频繁操作中不处理,直到操作完成之后(再过 delay 的时间)才一次性处理,执行最后一次操作
    function debounce(fn, delay) {
        delay = delay || 200;
        
        var timer = null;
    
        return function() {
            var arg = arguments;
              
            // 每次操作时,清除上次的定时器
            clearTimeout(timer);
            timer = null;
            
            // 定义新的定时器,一段时间后进行操作
            timer = setTimeout(function() {
                fn.apply(this, arg);
            }, delay);
        }
    };
    
    var count = 0;
    
    // 主体
    function scrollHandle(e) {
        console.log(e.type, ++count); // scroll
    }
    
    // 代理
    var proxyScrollHandle = (function() {
        return debounce(scrollHandle, 500);
    })();
    
    window.onscroll = proxyScrollHandle;

    缓存代理

    缓存代理 可以为一些开销大的运算结果提供暂时的缓存,在下一次运算时,如果传递进来的参数跟之前一致,则可以直接返回前面存储的运算结果。

    使用缓存代理计算乘法、加法

    // 计算乘法
    var mult = function(){
        var a = 1;
        for(var i = 0,ilen = arguments.length; i < ilen; i+=1) {
            a = a*arguments[i];
        }
        return a;
    };
    // 计算加法
    var plus = function(){
        var a = 0;
        for(var i = 0,ilen = arguments.length; i < ilen; i+=1) {
            a += arguments[i];
        }
        return a;
    }
    // 代理函数
    var proxyFunc = function(fn) {
        var cache = {};  // 缓存对象
        return function(){
            var args = Array.prototype.join.call(arguments,',');
            if(args in cache) {
                return cache[args];   // 使用缓存代理
            }
            return cache[args] = fn.apply(this,arguments);
        }
    };
    var proxyMult = proxyFunc(mult);
    console.log(proxyMult(1,2,3,4)); // 24
    console.log(proxyMult(1,2,3,4)); // 缓存取 24
    
    var proxyPlus = proxyFunc(plus);
    console.log(proxyPlus(1,2,3,4));  // 10
    console.log(proxyPlus(1,2,3,4));  // 缓存取 10
  • 相关阅读:
    Tomcat && Servlet
    List,Set,Collections工具类
    多表查询
    常用的API--集合
    msmpeng.exe阻止移动硬盘弹出
    接口400错误解析
    JDBC/Mybatis连接数据库报错:The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    tomcat启动报错:A child container failed during start
    PAT 1019 数字黑洞
    PAT 1017 A除以B
  • 原文地址:https://www.cnblogs.com/gaosirs/p/10750124.html
Copyright © 2011-2022 走看看