🎨
Notes
  • 持续更新中...
  • articles
    • browser
      • 深入理解现代浏览器 - 导航
      • 深入理解现代浏览器 - 架构
      • 深入理解现代浏览器 - 交互
      • 深入理解现代浏览器 - 渲染器进程
    • dsa
      • DSA - 并查集
      • DSA - 哈希表
      • DSA - AVL 树
      • DSA - 二叉树
      • 快速选择
      • Big O 算法复杂度
      • DSA - 栈和队列
      • DSA - 前缀树 Trie
      • DSA - 图
      • DSA - 链表
      • DSA - 递归
    • typescript
      • TypeScript 学习笔记 - 任意属性 (Indexable Types)
      • 力扣的 TypeScript 面试题
      • TypeScript 学习笔记 - as const
      • TypeScript 学习笔记 - infer
    • network
      • Internet Protocol (IP)
      • 计算机网络基础
      • 如何分辨同源和同站
      • DNS 如何查询 IP 地址?
    • vue
      • Nuxt.js 入门
      • 从零实现一个 Mini Vue
      • 从零实现一个简单的 VDOM 引擎
      • 从零实现一个响应式状态管理
    • sorting
      • 排序 - 归并排序
      • 排序 - 冒泡排序
      • 排序 - 选择排序
      • 排序 - 计数排序
      • 排序 - 插入排序
    • compile
      • Compiler and Interpreter
      • Just-In-Time (JIT) Compilers
      • 编译流程
    • others
      • 什么是上下文无关语法
      • 如何在终端打印出有颜色的字
    • dev-ops
      • github-actions
        • GitHub Action 简介
        • GitHub Actions for CI
    • workflow
      • 用 Node 写一个 cli
      • 如何规范 git commit 信息
      • 如何监听 git hooks
      • 如何规范代码风格 - prettier
      • 如何发布一个 npm package
      • 如何规范代码质量 - eslint
    • design-pattern
      • 代理模式
      • 单例模式
      • 策略模式
    • security
      • 点击劫持
      • CSP 内容安全策略
    • javascript
      • 尾调用优化
      • 4种常见的内存泄漏及解决方法
    • unit-test
      • Test Vuejs Application - Chapter 2
      • Test Vuejs Application - Chapter 1
      • Vue Unit Test Intro
    • performance
      • HTTP 缓存
      • 如何优化图片资源
Powered by GitBook
On this page
  • 目的
  • 问题 & 解决办法
  • 应用
  • 优点

Was this helpful?

  1. articles
  2. design-pattern

代理模式

Previousdesign-patternNext单例模式

Last updated 4 years ago

Was this helpful?

目的

当调用方不方便直接操作某个对象,又或者希望在访问对象之前或之后做某些操作时,可以使用代理模式。

  • 使用一个代理对象作为本体对象的替身;

  • 调用方访问代理对象,代理对象做完某些操作后,按照调用方的需求去访问本体对象,把结果返回给调用方;

https://cdn.jsdelivr.net/gh/suukii/Articles/assets/proxy_design_pattern.png

问题 & 解决办法

举个例子,我们有一个存放着超多数据的对象,如果把这个对象直接在程序中初始化的话,肯定会占据很多内存;而且,程序不一定一开始就需要用到这个对象,也不一定需要这个对象的所有数据;所以,比较经济的方法是,把这个超大对象放在服务端,当程序需要的时候再发起网络请求去访问。

问题是,在程序中可能不止一处要用到这个对象,我们总不想把发起网络请求的逻辑到处复制粘贴吧。而代理模式的思想就是,提供一个代理对象(替身),把这个代理对象伪装成本体对象,然后把本体对象藏起来。调用方需要数据的时候,就去访问代理对象,其实调用方是分不清自己在访问代理对象还是本体对象的,它也根本不需要区分。

用图解释大概是这个样子:

应用

代理模式大概有以下几种用途:

  • 惰性初始化:在真正需要的时候才通过代理对象去初始化本体对象,一般是本体对象消耗很大的时候才需要这样做;

  • 控制访问权限:代理对象负责甄别哪些调用方有权访问本体对象,对有权访问的调用方,代理对象把它们的请求转发给本体对象,对于无权访问的,就无视它们的请求;

  • 打印日志:想要记录某个对象的访问日志时,可以用一个代理对象来做这件事,这样就不需要对本体对象做修改;

  • 缓存请求结果:就像上例一样,代理对象负责发送网络请求并缓存请求结果,下次有同样的请求时可以直接返回缓存的数据;

  • 智能引用:可以用一个代理对象来记录某个对象当前有多少个引用,如果没有调用方引用这个本体对象,这个对象的内存就可以被及时释放了;

优点

  • 可以通过代理对象来控制本体对象而不必修改调用方代码和本体对象;

  • 可以很方便地引入多个代理对象,代理对象们可以链式访问(对代理对象来说,访问另一个代理对象和访问本体对象没什么不同);

唯一的修改是,把调用方的访问对象从本体对象改成代理对象,其他不变,因为代理对象是一个“伪本体对象”,在调用方看来,它和本体对象是一样的。

https://cdn.jsdelivr.net/gh/suukii/Articles/assets/proxy_design_pattern_1.png