设计模式之代理模式

1. 定义

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

2. 口语化表述

代理,在日常生活中很常见

比如找朋友替你拿个快递,此时的这个朋友就是代理者,并且按规范而言,他拿快递时,需要在快递单上的“代理签收”栏签上他的名字

此时的代理,就是替你签收快递的这个朋友,他能做一些需要你做的事(如,签收快递),也能对你的快递包裹做一些事情(如,他可以帮你拆包)

能代替你做一些事情,也能对这些事情做一些他的行为,这就是代理模式

下面的描述会沿用这个上述这个场景

3. 源码示例

代理在前端可太常见了,ES 6 中就有Proxy对象

ES 6 的Proxy对象,就是将需要代理的对象进行拦截,从而可以实现一些额外的操作

比如下面的示例:

const obj = {
    count: 0
}
// 对obj进行代理
const proxy = new Proxy(obj, {
    get(target, key) {
       // 拦截get方法并加入自定义的方法,这里是输出一句 "count: 0"
      return console.log("count:", target.count)
    }
})

obj.count // 0
proxy.count // "count: 0"

从代码可以看出,通过代理,可以实现拦截注入

代理是Vue实现响应式的核心原理,Vue3使用Proxy实现响应式数据对象

下面是Vue3的Reactive对象的创建函数:

function createReactiveObject(
 target: Target,
 isReadonly: boolean,
 baseHandlers: ProxyHandler<any>,
 collectionHandlers: ProxyHandler<any>,
 proxyMap: WeakMap<Target, any>
) {
    // ...
    // target already has corresponding Proxy
    const existingProxy = proxyMap.get(target)
    if (existingProxy) {
        return existingProxy
    }
    // only specific value types can be observed.
    const targetType = getTargetType(target)
    if (targetType === TargetType.INVALID) {
        return target
    }
    const proxy = new Proxy(
        target,
        targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers
    )
    proxyMap.set(target, proxy)
    return proxy
}

可以看到,Vue3中使用代理实现响应式对象,从而实现数据的实时渲染

4. 总结

4.1 设计优点

  • 在客户端毫无察觉的情况下控制服务对象

  • 客户端对服务对象的生命周期进行管理

  • 开闭原则

    可以在不对原始对象做出修改的情况下创建新代理

4.2 适用场景

  • 访问控制(保护代理)

  • 缓存请求结果(缓存代理)

  • 延迟初始化(虚拟代理)

5. 参考资料

[1] 代理设计模式 (refactoringguru.cn)

[2] core/packages/reactivity/src/reactive.ts at main · vuejs/core (github.com)

posted @ 2023-12-06 13:32  当时明月在曾照彩云归  阅读(6)  评论(0编辑  收藏  举报