00、基本概念

单例模式(Singleton Pattern),也称单体模式,就是全局(或某一作用域范围)唯一实例,大家共享、复用一个实例对象,也可减少内存开销。单例模式应该是最基础、也最常见的设计模式了。

常见场景

  • 全局状态vuex,Jquery中的全局对象$,浏览器中的window、document 都算是单例。
  • 公共的服务、全局配置、缓存、登录框等,全局复用一个对象。

所以实现单例模式的关键就是保障对象实例只创建一次,后续的引用都是同一个实例对象。相比于Java、C#等语言,JavaScript单线程,也没有类,单例实现还是比较容易,基于JS语言特性,有多种实现思路。

实现方式 说明
全局对象 全局环境下的var变量,或者直接挂载到全局对象window上。使用简单,但会存在全局污染,也不优雅,不推荐!
构造函数.静态方法getInstance 使用构造函数的静态方法getInstance()来获取实例,唯一实例对象存储在构造函数的instance上。
虽有一定耦合,Class版本还是一种不错的方式
闭包-new 利用JS的闭包(万恶的闭包)来保存那个唯一对象实例,这样就可以new来获取唯一实例对象了
ES6模块Module ES6的模块其实就是单例模式,模块中导出的对象就是单例的,多次导入其实是同一个引用。

01、全局对象(不推荐)

创建一个全局对象,浏览器中全局对象一般挂载在Window上,如JQuery、loadsh就是如此实现的。

  • 在全局环境中用 var 字面量申明一个对象,利用了var的变量提升 + 全局属性的特点(全局环境下的var变量会自动成为全局属性),所以慎用var
  • 直接挂载到全局对象window上。
window.jQuery = window.$ = jQuery;
window._ = lodash; // 全局环境下的var变量会自动成为全局属性
var singleUser = {
name: 'sam',
id: 1001
}
// 使用
console.log(singleUser.name) // sam
console.log(window.singleUser.name) // sam

02、构造函数.静态方法getInstance

统一一个入口获取对象实例,入口就是为构造函数的静态方法getInstance()(当然命名随意),在该函数中判断(静态)对象instance是否初始化,没有则创建,有则直接返回。所以实际上的唯一实例是作为静态属性,保存在构造器的instance属性上,类似Math.PI

function GlobalUser(name) {
this.name = name
this.id = 1002
}
// 基于构造函数的静态函数作为统一入口,Constructor.getInstance()
GlobalUser.getInstance = function(name) {
// 注意这里的this指向的是构造函数GlobalUser
if (this.instance) return this.instance
// 第一次没有创建
return this.instance = new GlobalUser(name)
}
console.log(GlobalUser.getInstance('张三').name) // 张三
console.log(GlobalUser.getInstance('李四').name) // 张三,依然是张三,复用了第一次创建的实例
console.log(GlobalUser.getInstance() === GlobalUser.getInstance()) // true

ES6的Class 版本的,原理和上面一样,因为Class本质上也是基于原型的构造函数,但实现起来更优雅一些,推荐使用。

class GlobalUser {
constructor(name) {
this.name = name
this.id = 1002
}
static getInstance(name) {
//静态方法属于类本身,这里的this也就指向类本身
if (!this.instance)
this.instance = new GlobalUser(name)
return this.instance;
}
}
console.log(GlobalUser.getInstance('张三').name) // 张三
console.log(GlobalUser.getInstance('李四').name) // 张三,依然是张三,复用了第一次创建的实例
console.log(GlobalUser.getInstance() === GlobalUser.getInstance()) // true

03、闭包-new

核心思路就是利用JS的闭包(万恶的闭包)来保存那个唯一对象实例,这样就可以new来获取唯一实例对象了!基于闭包的实现方式是比较多的,下面示例只是其中一种,但基本原理都是利用闭包来保存那个“唯一实例”。

let GlobalUser = (function() {
let instance // 闭包保存的唯一实例对象
return function(name) {
if (instance) return instance
// (首次)创建实例
instance = { name: '张三', id: 1003 }
return instance
}
})() // 立即执行,外层函数的价值就是他的闭包变量instance
console.log(new GlobalUser('张三').name) // 张三
console.log(new GlobalUser('李四').name) // 张三,依然是张三,复用了第一次创建的实例
console.log(new GlobalUser() === new GlobalUser()) // true

断点输出一下日志可以看到GlobalUser的构造函数闭包

闭包版本还可以继续改进下,做成一个通用版本的单例工厂:把具体的对象示例构造器封装一下。

// 一个通用单例工厂,参数为构造器函数、Class类
let Singleton = function(Constructor) {
let instance
return function(...args) {
if (instance) return instance
// (首次)创建实例
instance = new Constructor(...args)
return instance
}
} // 构造函数
function User(name) {
this.name = name
}
class Config {
constructor(title) {
this.title = title
}
}
// 使用
let SingleUser = Singleton(User)
let u1 = new SingleUser('sam')
let u2 = new SingleUser('zhangsan')
console.log(u1 === u2, u1, u2) //true User {name: 'sam'} User {name: 'sam'} let GlobalConfig = Singleton(Config)
console.log(new GlobalConfig('设计') === new GlobalConfig('模式')) // true

04、ES6模块Module

ES6的模块其实就是单例模式,模块中导出的对象就是单例的,多次导入其实是同一个引用。

回顾一下ESM:参考《ESModule模块化

  • Singleton 模式:import模块的代码只会执行一次,同一个url文件只会第一次导入时执行代码。后续任何地方import都不会执行模块代码了,也就是说,import语句是 Singleton 模式的。
  • 只读-共享:模块导入的接口的是只读的,不能修改。当然引用对象的属性值是可以修改的,不建议这么干,注意模块是共享的,导出的是一个引用,修改后其他方也会生效。

因此用ESM实现单例就比较简单了:

// 模块申明 config.js
export default {
title: '设计模式'
} // 使用
import config from './config.js'
console.log(config) // {title: '设计模式'}
config.title = '修改一下' import config2 from './config.js'
console.log(config, config2) // {title: '修改一下'} {title: '修改一下'}

参考资料


️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

前端设计模式:单例模式(Singleton)的更多相关文章

  1. 设计模式 单例模式(Singleton) [ 转载2 ]

    设计模式 单例模式(Singleton) [ 转载2 ] @author java_my_life 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类 ...

  2. 设计模式 单例模式(Singleton) [ 转载 ]

    设计模式 单例模式(Singleton) [ 转载 ] 转载请注明出处:http://cantellow.iteye.com/blog/838473 前言 懒汉:调用时才创建对象 饿汉:类初始化时就创 ...

  3. JAVA设计模式-单例模式(Singleton)线程安全与效率

    一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...

  4. 浅谈设计模式--单例模式(Singleton Pattern)

    题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...

  5. 设计模式 - 单例模式 Singleton Pattern - C#

    单例模式 Singleton Pattern 1.单例模式设计模式属于创建型模式 2.是单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方式,可以直接访 ...

  6. [工作中的设计模式]单例模式singleton

    一.模式解析: 单例模式是最简单和最常用的设计模式,面试的时候,不管新毕业的学生还是已经工作多年的筒子,对单例模式基本都能聊上两句.单例模式主要体现在如下方面: 1.类的构造函数私有化,保证外部不能直 ...

  7. 23种设计模式--单例模式-Singleton

    一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...

  8. 设计模式--单例模式Singleton(创建型)

    单例模式很显然是定义一个类,这个类在程序中只有唯一的实例对象.一般单例类的构造函数是私有的,只能通过调用静态函数GetInstance来获取实例. 一.单例模式有三种:懒汉式单例.饿汉式单例.登记式单 ...

  9. 设计模式--单例模式Singleton

    单例模式顾名思义整个程序下只有一个实例,例如一个国家只有一个皇帝,一个军队只有一个将军.单例模式的书写又分为饿汉模式和懒汉模式 饿汉模式   类中代码 package demo; public cla ...

  10. 设计模式——单例模式(Singleton)

    保证一个类仅有一个实例,并提供一个访问它的全局访问点.——DP UML类图 模式说明 个人认为单例模式是所有设计模式中最为简单的一个模式,因为实现这个模式仅需一个类,而不像其他模式需要若干个类.这个模 ...

随机推荐

  1. 图解Redis和Zookeeper分布式锁

    1.基于Redis实现分布式锁 Redis分布式锁原理如上图所示,当有多个Set命令发送到Redis时,Redis会串行处理,最终只有一个Set命令执行成功,从而只有一个线程加锁成功 2:SetNx命 ...

  2. iOS中容易用错的常用知识点

    坐标系转换 ios中的坐标系有三种 视图坐标系:原点(0,0)视图的左上角 窗口坐标系:原点(0,0)窗口的左上角 世界坐标系:原点(0,0)游戏中世界的原点 平时开发中经常会遇到转UIWindow坐 ...

  3. CKS 考试题整理 (18)-TLS 安全配置

    Task 通过 TLS 加强 kube-apiserver 安全配置,要求 kube-apiserver 除了 VersionTLS13 及以上的版本可以使用,其他版本都不允许使用. 密码套件(Cip ...

  4. Centos6yum源切换

    CentOS 6操作系统版本结束了生命周期(EOL),Linux社区已不再维护该操作系统版本.建议您升级操作系统至CentOS 7及以上,如果您的业务过渡期仍需要使用CentOS 6系统中的一些安装包 ...

  5. 使用React和Redux进行前端应用程序:现代Web应用程序框架

    目录 标题:<27. 使用 React 和 Redux 进行前端应用程序:现代 Web 应用程序框架> 背景介绍: 随着现代 Web 应用程序的发展,前端开发人员需要一种高效的.灵活的框架 ...

  6. Cisco show interface 命令详解

    Router#show interface f0/2 FastEthernet0/2 is up, line protocol is up Hardware is Lance, address is ...

  7. 零基础实现Java直播(一):集成

    从泛娱乐的秀场直播,到直播带货潮流中的电商直播,直播已经成为2020年最热的应用技术之一,越来越多的产品希望加入直播功能.下面我们基于即构Express Video SDK,来分享如何从零实现线上直播 ...

  8. 即构自研海量有序数据网络MSDN,构建全球可靠的多云通讯链路

    2020是实时音视频技术应用大爆发的一年,电商直播.视频会议.在线课堂等多个场景获得了广泛关注.即构科技作为全球领先的云通讯商,截止目前已服务超过4000家企业客户,每日音视频通话时长超过20亿分钟, ...

  9. 即构SDK5月迭代:新增声道选择、网络探测、智能消噪等功能,打造更优的视听体验

    即构SDK5月份的迭代更新如期而至,本月互动视频(LiveRoom).实时语音(AudioRoom)两大SDK以及录制插件(PlayRecord)均有新功能上线.新增的声道选择.变调控制.智能消噪.枚 ...

  10. eclipse在主题商城下载安装黑色主题

    Eclipse配置黑色主题方法: 1. 借用国外一个Elipse主题网站分享的主题配置文件来配置一个黑色的主题. 主题网址 2. 在这个网站下载自己喜欢的主题,单击主题进入下载页面,建议大家选择EPF ...