🎨
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
  • 单例模式 vs 全局变量
  • 实现思路
  • 实现代码
  • 优点

Was this helpful?

  1. articles
  2. design-pattern

单例模式

单例模式就是一个 class 永远都返回同一个实例,而且这个实例还可以在全局中访问到。

听起来是不是很像一个全局变量?

单例模式 vs 全局变量

  • 同样都是全局可访问,全局变量有被其他代码修改的风险,而单例模式提供的实例不能通过外部代码来修改替换,除非这个 class 暴露了修改实例的方法。

  • 单例模式还能封装一些代码逻辑。

实现思路

单例模式永远返回同一个实例对象,所以我们不能使用普通的构造函数来实现,因为每次 new 的时候都会创建一个新的实例。

其实如果是 JS 的普通构造函数语法的话,new 的时候如果函数中返回一个对象,那 new 出来的对象就会被丢弃,然后我们也可以把单例对象作为构造函数的静态属性缓存起来,不过这样我们也把单例对象暴露出去了。

我们得把构造函数和单例对象隐藏起来,然后另外暴露一个获取单例对象的方法。在这个方法中,我们需要实现的是:

  1. 首次调用时,在方法中调用隐藏的构造函数,创建实例对象并缓存起来;

  2. 之后的调用就直接返回缓存的实例对象;

实现代码

因为 JS 的 class 还不支持私有属性,所以我们先用一个 IIFE 来实现单例模式。

let count = 0

const Singleton = (function () {
  // 缓存单例实例对象
  let instance = null

  // 只有首次调用 getInstance 方法时才会用 new 调用 Constructor 方法
  // 外部代码无法通过 new 调用 Constructor 创建实例对象
  // Contructor 只会执行一次
  function Constructor() {
    count++
  }

  function getInstance() {
    // 首次调用,创建单例实例并缓存
    if (!instance) {
      instance = new Constructor()
    }
    // 之后调用,直接返回缓存的实例对象
    return instance
  }
  // 暴露获取单例对象的方法
  return {
    getInstance
  }
})()

const a = Singleton.getInstance()
const b = Singleton.getInstance()
console.log(a === b) // true
console.log(count) // 1

优点

  • 保证了一个 class 只有一个实例;

  • 这个实例是全局可访问的;

  • 惰性初始化,单例对象只有在首次获取的时候才会被创建,这也是和全局变量不同的一个点。

Previous代理模式Next策略模式

Last updated 4 years ago

Was this helpful?