JavaScript设计模式及代码实现——单例模式
单例模式

1 定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2 应用时机
- 当一个类的实例被频繁使用,如果重复创建这个实例,会无端消耗资源。比如 dialog 弹窗会被全局重复使用
- 业务功能本身决定了全局只能有唯一的实例。比如 redux 管理的数据,只能有唯一的一份
3 应用场景
- 对于前端应用的许多基本组件:比如 dialog、message等等,会被全局频繁使用,就应该维护一个全局唯一的实例,避免重复创建带来不必要的资源消耗。业务组件也同理:比如购物车组件、登录弹窗组件等
- 对于一些通用的工具库,经常会使用单例模式。比如我们通常会创建一个全局唯一的 axios 实例来发起网络请求
- 对于 redux、vuex 等状态管理库,都采用全局唯一的 store 来存储应用状态数据
等等 ……
4 代码实现
4.1 全局变量和命名空间
根据单例模式的定义
// 维护类 A 的唯一实例
class A {}
window.a = new A(); // 或 global.a = new A(); 浏览器用 window
这种方法存在很明显的缺陷,因为同一项目的所有程序员都可以定义全局的变量 a,很容易造成全局污染。
解决办法是设定一个自己的命名空间来和其他人区分
// 比如我设定自己的命名空间 JiMing
window.JiMing = {
a: new A()
}
如果使用 TypeScript ,可以使用关键字 namespace
namespace JiMing {
export const a = new A();
}
4.2 惰性单例
上述实现中,我们直接在全局创建了类 A 的单一实例,无论其是否被使用,这在某些场景会造成资源浪费。有时我们希望在用到的时候再创建实例
如下代码利用立即执行函数和闭包来得到 A 的单例获取函数:getSingletonOfA
class A {}
const getSingletonOfA = (() => {
let instance;
return () => {
return (instance ??= new A());
};
})();
只有在调用getSingletonOfA才会创建 A 的实例,并且会在闭包中将其储存在 instance 中,重复调用getSingletonOfA会获取相同的实例
const a1 = getSingletonOfA();
const a2 = getSingletonOfA();
console.log(a1 === a2); // true
上述方法能够满足单例模式,但是不够通用,改造如下
const createSingletonUtil = (className) => {
let instance;
return () => {
return (instance ??= new className());
};
};
我们封装一个工具函数createSingletonUtil,调用该函数后可以获得任意类的“单例获取函数”
const getSingletonOfA = createSingletonUtil(A);
const a3 = getSingletonOfA();
const a4 = getSingletonOfA();
console.log(a3 === a4); // true
createSingletonUtil 的 TypeScript 实现如下:
class A {}
const createSingletonUtil = <T>(className: new () => T) => {
let instance: T;
return () => {
return (instance ??= new className());
};
};
const getSingletonOfA = createSingletonUtil<A>(A);
const a1 = getSingletonOfA();
const a2 = getSingletonOfA();
console.log(a1 === a2);
当然惰性单例也有缺点,对于某些类,如果创建实例需要较长时间,这时在用到的时候再创建恐怕来不及,可能会产生其他副作用,比如造成页面卡顿。在此场景下,在应用初始化时就创建其实例或许会有更好的用户体验
上述两种方法根据不同的业务场景择一使用即可
公众号【今天也要写bug】(op-bot)提问答疑
JavaScript设计模式及代码实现——单例模式的更多相关文章
- JavaScript设计模式与开发实践 - 单例模式
引言 本文摘自<JavaScript设计模式与开发实践> 在传统开发工程师眼里,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返 ...
- JavaScript设计模式(二) - 单例模式
什么是单例模式? 单例模式从字面上的理解是不困难的,js上就是指只有一个对象实例. 为什么需要单例模式? 我们可以将一些成员变量封装在一个单例对象中,每次访问这些变量都只能从这个单例对象进行访问,这样 ...
- JavaScript设计模式样例四 —— 单例模式
单例模式(Singleton Pattern): 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 目的:阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例. 场景: ...
- JavaScript 设计模式及代码实现——代理模式
代理模式 1 定义 为其他对象提供一种代理以控制对这个对象的访问 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 2 应用举例 2.1 缓 ...
- Javascript设计模式笔记
Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...
- JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)
(转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...
- 《javascript设计模式》读书笔记四(单例模式)
1.单利模式简单介绍 在<设计模式>中单利模式是一种比較简单的模式,定义例如以下: 确保某一个类仅仅有一个实例,并且自行实例化并向整个系统提供这个实例. 在javascript中则将代码组 ...
- 探索Javascript设计模式---单例模式
最近打算系统的学习javascript设计模式,以便自己在开发中遇到问题可以按照设计模式提供的思路进行封装,这样可以提高开发效率并且可以预先规避很多未知的问题. 先从最基本的单例模式开始. 什么是单例 ...
- 再起航,我的学习笔记之JavaScript设计模式10(单例模式)
单例模式 单例模式(Singleton) : 又被称为单体模式,是只允许实例化一次的对象类.一个类有且仅有一个实例,并且自行实例化向整个系统提供. 命名空间 单例模式可能是JavaScript中我们最 ...
随机推荐
- MCDF实验2
目录 接口的使用 仿真的结束 类的例化和类的成员 接口的使用 问题1.1:可以看到之前的实验 channel initiator 发送的数据例如 valid 和 data 与时钟 clk 均在同 ...
- 开发工具-在线生成GUID
更新记录 2022年6月11日 记录开始. https://www.toolbaba.cn/d/dev_guid http://tool.pfan.cn/guidgen https://www.iam ...
- 在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在进行项目开发的时候,刚好需要用到对字符串表达式进行求值的处理场景,因此寻找了几个符合要求的第三方组件LambdaParser.DynamicExpresso.Z.Expressions,它们各自功能 ...
- 关于个人项目(臻美MV【仿抖音App】)滑动切换视频的分析(前端角度)
我们知道你天天刷抖音的时候可以上滑切换视频,互不影响.那么我们站在前端的角度能否可以实现这种效果呢?这是我的个人项目:臻美MV 下面我是用Vue写的,现在我把它开源. Vue: 初始界面 <te ...
- 压测工具Apache Bench的安装与使用
压测工具使用指南: Apache Bench 下载64位 压缩 cmd打开bin目录 使用abs.exe [option] http[s]://www.asb.com 来测试 其中option: -n ...
- iOS OC纯代码企业级项目实战之我的云音乐(持续更新))
简介 这是一个使用OC语言,从0使用纯代码方式开发一个iOS平台,接近企业级商业级的项目(我的云音乐),课程包含了基础内容,高级内容,项目封装,项目重构等知识:主要是讲解如何使用系统功能,流行的第三方 ...
- docker下node环境搭建
初始化⼀个NodeJs程序 以下操作必须已经安装了NodeJS. ⾸先创建⼀个空⽂件夹.并创建以下⽂件: server.js package.json Dockerfile .dockerignore ...
- 记一次 Druid 超时配置的问题 → 引发对 Druid 时间配置项的探究
开心一刻 一天在路边看到一个街头采访 记者:请问,假如你儿子娶媳妇,给多少彩礼合适呢 大爷:一百万吧,再给一套房,一辆车 大爷沉思一下,继续说到:如果有能力的话再给老丈人配一辆车,毕竟他把女儿养这么大 ...
- 【docker专栏6】详解docker容器状态转换管理命令
docker容器有三种状态运行.停止.暂停,镜像可以创建.运行容器,镜像和容器也可以转换成tar压缩包进行存储.本文为大家介绍容器的状态转换命令及镜像创建运行容器.tar包导入导出相关的命令及使用场景 ...
- 可落地的DDD(7)-战术设计上的一些误区
背景 几年前我总结过DDD战术设计的一些落地经验可落地的DDD(5)-战术设计,和一次关于聚合根的激烈讨论最近两年有些新的落地体验,回过头来发现,当初对这些概念的理解还是没有深入,这篇文章重新阐述下. ...