情景: 小明追女生 A
- 非代理模式: 小明 =花=> 女生 A
- 代理模式: 小明 =花=> 让女生 A 的好友 B 帮忙 =花=> 女生 A
- 代理对象和本体对象具有一致的接口, 对使用者友好
代理模式的种类有很多, 在 JS 中最常用的为虚拟代理和缓存代理。
下面这段代码运用代理模式来实现图片预加载, 可以看到通过代理模式巧妙地将创建图片与预加载逻辑分离, 并且在未来如果不需要预加载, 只要改成请求本体代替请求代理对象就行。
const myImage = (function() {
const imgNode = document.createElement('img')
document.body.appendChild(imgNode)
return {
setSrc: function(src) {
imgNode.src = src
}
}
})()
const proxyImage = (function() {
const img = new Image()
img.onload = function() { // http 图片加载完毕后才会执行
myImage.setSrc(this.src)
}
return {
setSrc: function(src) {
myImage.setSrc('loading.jpg') // 本地 loading 图片
img.src = src
}
}
})()
proxyImage.setSrc('http://loaded.jpg')
const mult = function() {
let a = 1
for (let i = 0, l; l = arguments[i++];) {
a = a * l
}
return a
}
const proxyMult = (function() {
const cache = {}
return function() {
const tag = Array.prototype.join.call(arguments, ',')
if (cache[tag]) {
return cache[tag]
}
cache[tag] = mult.apply(this, arguments)
return cache[tag]
}
})()
proxyMult(1, 2, 3, 4) // 24
在开发时候不要先去猜测是否需要使用代理模式, 如果发现直接使用某个对象不方便时, 再来优化不迟。