JavaScript设计模式(三):代理模式

代理模式

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

简单理解就是你想使用一个东西,但是你不能直接用,你必须通过一个中间商来使用,就像你想要找老板加工资,但不让你直接见老板,而是需要去找老板的助理,通过助理反馈给老板让他给你加工资。

代理模式其实也很常见,我们在写页面时,一个父节点下有很多子节点,每次点击子节点都需要触发事件,我们肯定不会挨个子节点去添加事件,而是会在让他的父节点做代理,通过冒泡到父节点触发事件。

保护代理

通过代理过滤掉一些根本不符合执行条件的情况。

例如我们有个方法去请求一些数据,后面突然需要加一些判断条件,不满足条件的就没必要再发送一次无用的请求了,这里就可以通过保护代理的方式,将筛选条件放在代理中去过滤,原本的方法还是纯粹的请求数据逻辑。
这样处理的好处就是不会去破环原来的逻辑,把筛选的逻辑放在代理中单独处理也更方便定位问题,代码更加清晰。

虚拟代理:使用代理模式实现图片预加载

通过代理,在真正需要执行方法的时候再触发。

1
2
3
4
5
6
7
8
9
var myImage = (function () {
var imgNode = new Image(500,500);
document.body.appendChild(imgNode);
return {
setSrc: function (src) {
imgNode.src = src;
}
}
})();

首先创建一个 Image 对象,把他的 setSrc 方法暴露出去。

1
2
3
4
5
6
7
8
9
10
11
12
var proxyImage = (function () {
var img = new Image(500, 500);
img.onload = function () {
myImage.setSrc(this.src);
}
return {
setSrc: function (src) {
myImage.setSrc('./loading.gif');
img.src = src;
}
}
})();

接着在定义一个代理对象,该方法同时也拥有 setSrc 方法,只不过在这里代理了设置原对象的方法,在真正的图片加载完成之前,会用其他图片代替展示,避免出现页面空白的情况。

1
proxyImage.setSrc('https://www.bing.com/th?id=OHR.JohnDayFossil_EN-CN3221993722_tmb.jpg');

最后我们通过代理对象来设置图片的 src ,代理对象相当于拦截了对于真正对象的操作,在图片加载完成后才执行真正的赋值。

缓存代理:使用代理模式实做数据缓存

缓存代理主要就是对于一些计算开销比较的大的时候,通过代理实现缓存,减少重复计算。

先实现一个计算斐波那契数列的方法

1
2
3
4
5
6
7
8
function fibonacci(n) {
if (n <= 1) return n;
let fib = [0, 1];
for (let i = 2; i <= n; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
return fib[n];
}

然后加入代理

1
2
3
4
5
6
7
8
9
const proxyFibonacci = (function () {
let cache = {};
return function (num) {
if (!cache[num]) {
cache[num] = fibonacci(num);
}
return cache[num];
}
})()

在代理里面我们使用闭包,用 cache 来缓存计算值,这样计算过的值我们通过代理直接读取缓存即可,减少计算的过程,提高性能。这种方式在计算方法开销很大的情况下很有用。


JavaScript设计模式(三):代理模式
https://l1ushun.github.io/2023/10/11/design-proxy/
作者
liu shun
发布于
2023年10月11日