Javascript 设计模式 - 代理模式(Proxy Pattern)

1,606 阅读1分钟

代理模式(Proxy Pattern)

为其他对象提供一种代理以控制对这个对象的访问。

常用的代理模式变种有以下几种:

  • 保护代理
  • 虚拟代理
  • 缓存代理

1. 保护代理

保护代理用于控制不同权限的对象对目标对象的访问

  • 举例
class Car {
    drive() {
        return "driving";
    };
}

class CarProxy {
    constructor(driver) {
        this.driver = driver;
    }
    drive() {
        // 保护代理,仅18岁才能开车
        return (this.driver.age < 18) ? "too young to drive" : new Car().drive();
    };
}

2. 虚拟代理

虚拟代理可应用于:图片懒加载惰性加载合并http请求

  • 举例:图片懒加载
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>图片懒加载</title>
    <style>
        img {
            display: block;
            width: 400px;
            height: 300px;
            margin-bottom: 200px;
        }
    </style>
</head>
<body>
    <img data-src="./images/1.jpg" alt="">
    <img data-src="./images/2.jpg" alt="">
    <img data-src="./images/3.jpg" alt="">
    <img data-src="./images/4.jpg" alt="">
</body>
<script>
    var imgs = document.querySelectorAll('img');
    //offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
    function getTop(e) {
    var T = e.offsetTop;
        while(e = e.offsetParent) {
            T += e.offsetTop;
        }
        return T;
    }
    function lazyLoad(imgs) {
        var H = document.documentElement.clientHeight;//获取可视区域高度
        var S = document.documentElement.scrollTop || document.body.scrollTop;
        for (var i = 0; i < imgs.length; i++) {
            if (H + S > getTop(imgs[i])) {
                imgs[i].src = imgs[i].getAttribute('data-src');
            }
        }
    }
    window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
        lazyLoad(imgs);
    }
</script>
</html>

3. 缓存代理

缓存代理可应用于:缓存ajax异步请求数据计算乘积

  • 举例:缓存ajax请求数据
const getData = (function() {
    const cache = {};
    return function(url) {
        if (cache[url]) {
            return Promise.resolve(cache[url]);
        }
        return $.ajax.get(url).then((res) => {
            cache[url] = res;
            return res;
        }).catch(err => console.error(err))
    }
})();

getData('/getData'); // 发起http请求
getData('/getData'); // 返回缓存数据

总结

代理模式包括许多小分类,在 JavaScript 开发中最常用的是虚拟代理和缓存代理。虽然代理模式非常有用,但我们在编写业务代码的时候,往往不需要去预先猜测是否需要使用代理模式。当真正发现不方便直接访问某个对象的时候,再编写代理也不迟。