Skip to main content

Proxy

通过一个代理对象:

  • 临时存储原对象方法调用产生的一系列结果 (新建对象), 减少重复对象的产生.
  • 代理对象可以为中间过程透明地增加额外逻辑: 预加载/缓存/合并/验证/转换等.
  • 昂贵的对象创建或任务执行可以延迟到代理对象中执行.
  • 代理类型: 远程/保护/虚拟/缓存代理.
  • 符合开放封闭原则.
Proxy Use Case
  • 远程代理:
    • 代理软件.
    • 防火墙代理.
  • 保护代理:
    • 跨域处理.
    • 路由保护代理.
  • 虚拟代理:
    • 图片预加载.
    • 智能引用代理: C++ smart pointer, Rust RefCell, Linux file descriptor.
    • 写时拷贝代理: 内存页, DLL.
  • 缓存代理:
    • 缓存函数.
    • 缓存服务器: React Query (cache data).

代理模式强调一种关系 (Proxy 与它的实体之间的关系), 这种关系可以静态地表达. 装饰者模式用于一开始不能确定对象的全部功能. 代理模式通常只有一层代理-本体的引用, 装饰者模式经常会形成一条长长的装饰链.

class Percentage {
constructor(percent) {
this.percent = percent
}

toString() {
return `${this.percent}&`
}

valueOf() {
return this.percent / 100
}
}

const fivePercent = new Percentage(5)
console.log(fivePercent.toString())
console.log(`5% of 50 is ${50 * fivePercent}`)
function GeoCoder() {
this.getLatLng = function (address) {
if (address === 'Amsterdam')
return '52.3700° N, 4.8900° E'
else if (address === 'London')
return '51.5171° N, 0.1062° W'
else if (address === 'Paris')
return '48.8742° N, 2.3470° E'
else if (address === 'Berlin')
return '52.5233° N, 13.4127° E'
else return ''
}
}

function GeoProxy() {
const geocoder = new GeoCoder()
const geocache = {}

return {
getLatLng(address) {
if (!geocache[address])
geocache[address] = geocoder.getLatLng(address)

log.add(`${address}: ${geocache[address]}`)
return geocache[address]
},
getCount() {
let count = 0

for (const code in geocache) count++

return count
},
}
}

Proxy in Vue:

const original = { name: 'jeff' }

const reactive = new Proxy(original, {
get(target, key) {
console.log('Tracking: ', key)
return target[key]
},
set(target, key, value) {
console.log('updating UI...')
return Reflect.set(target, key, value)
},
})

console.log(reactive.name) // 'Tracking: name'
reactive.name = 'bob' // 'updating UI...'