JS设计模式之“单孑独立” - 单例模式

2024-09-03 13:52

本文主要是介绍JS设计模式之“单孑独立” - 单例模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

image.png

image.png

引言

JavaScript开发中,单例模式是一种常见且实用的设计模式一。

单例模式的核心思想是:确保一个类只有一个实例对象,并且该对象可以在应用程序的任何地方被共享和访问。通过使用单例模式,我们可以简化代码、节省资源、方便管理和共享功能,并提高代码的可维护性和可读性。

然而,单例模式并不是适用于所有场景的万能解决方案。设计应用程序时,应该权衡单例模式的优点和缺点,并根据具体需求合理地使用。特别是在需要可维护性和代码复用性的情况下,我们需要考虑其他设计模式或者结合使用多种模式来解决问题。

在本篇文章中,我们将深入探讨JavaScript中的单例模式,包括应用场景、实现方式、优缺点以及最佳实践。通过学习单例模式,我们将更好地理解如何设计和构建高质量的JavaScript应用程序。

一、什么是单例模式

1.1 定义

定义:单例模式是指一个类只能有一个实例,通过自身实例化并提供一个访问该实例的全局访问点。

单例模式是一种比较常见的设计模式,旨在确保一个类只有一个实例对象,并提供一个全局访问点以访问该实例。

在单例模式中,类只能实例化一次,任何其他的实例化操作都会返回相同的实例。这样可以确保在整个程序中,只有一个实例对象存在,避免了多次创建相同对象的浪费。

1.2 特点

  1. 类只能有一个实例对象。

  2. 提供一个全局访问点,使该实例可以被外部访问。

  3. 延迟初始化,即实例化过程只会发生一次。

1.3 应用场景

  1. 对象只需要被实例化一次,当一个对象在系统中只需要存在一个实例时。

  2. 创建一个全局的共享资源,例如配置文件、日志文件等。

  3. 配置信息的管理,确保系统中的各个组件都可以共享和访问配置信息。

  4. 管理唯一标识符,例如全局唯一的序列号生成器、订单号生成器等。

二、实现单例模式的几种方法

image.png

image.png

2.1 懒汉式

懒汉式是一种延迟初始化的单例模式实现方式,即在首次使用时才会创建实例。懒汉式是一种比较常见的单例模式实现方式,可以延迟初始化实例,节省资源。但需要注意多次实例化问题,可以采用加锁或双重检查锁定方式来解决。

在懒汉式中,只有当需要获取单例对象时才会创建它。但是要保证有且只有一个创建单例对象。通过使用判断实例对象来避免多个调用同时创建多个实例的问题。

class Singleton {constructor() {// ... 初始化操作}static getInstance() {if (!this.instance) {this.instance = new Singleton();}return this.instance;}
}

通过 getInstance 方法来获取实例。在首次调用 getInstance 时,会判断实例是否已经存在,如果不存在则创建一个新的实例。通过使用静态变量this.instance来保存实例,确保全局只有一个实例对象。

2.2 饿汉式

饿汉式是一种在类加载时就创建实例的单例模式实现方式。在这种方式中,实例在类加载时就被创建,无论是否使用到该实例。饿汉式是一种简单便捷的单例模式实现方式。但需要注意实例的创建时机和资源消耗。

class Singleton {constructor() {// ... 初始化操作}static getInstance() {return this.instance;}
}Singleton.instance = new Singleton();

在这种饿汉式的实现方式中,实例被声明为类的静态成员,并在类加载时就已经创建完毕。通过 getInstance 方法来获取这个实例。

由于实例在类加载时就被创建,可以保证全局只有一个实例对象。每次调用 getInstance 方法时直接返回该实例,不需要额外的判断和创建操作。

饿汉式的优点是简单快捷。缺点是在类加载时就创建实例,无论是否被使用到,可能会消耗一定的资源。而且,该实现方式不支持延迟初始化,可能会降低系统的启动速度。

2.3 推荐的单例模式实现方式

2.3.1 使用 JavaScript 闭包

JavaScript闭包模块化的思想是将相关的功能封装到一个独立的模块中,并只暴露出一个公共接口。这种方式天然地具备了单例模式的特点,因为模块在被调用时只会被实例化一次。例如:

const singleton = (function () {// 私有变量和方法let instance;function init() {// ... 初始化操作return {// ... 公共接口};}// 返回一个实例化对象return {getInstance: function () {if (!instance) {instance = init();}return instance;},};
})();// 使用方式
const instance = singleton.getInstance();
2.3.2 ES6 的单例模式

ES6 中引入了 class 的概念,可以通过 class 和静态属性的方式来实现单例模式。例如:

class Singleton {constructor() {// ... 初始化操作}static getInstance() {if (!Singleton.instance) {Singleton.instance = new Singleton();}return Singleton.instance;}
}// 使用方式
const instance = Singleton.getInstance();

三、单例模式的优缺点

从以上的学习中,我们可以总结JavaScript 单例模式的优点和缺点如下:

3.1 优点

  1. 提供了一种简单且有效的方式来确保只有一个实例对象被创建并且全局可访问。

  2. 可以避免全局变量的污染,将相关的功能组织在一个独立的实例中,提高代码的可维护性和可读性。

3.2 缺点

  1. 单例模式可能会引入全局状态,对代码的可测试性和可维护性造成影响。因为单例模式的实例通常是全局可访问的,对于其他模块的代码来说,可能无法轻松模拟或替换该实例。

  2. 单例模式的依赖关系和耦合度较高,它需要在全局范围内共享状态,修改代码逻辑时需要小心翼翼地处理依赖关系。

  3. 单例模式在某些场景下可能导致性能问题,特别是在实例较为庞大或者需要大量计算的情况下。因为单例模式在初始化时就创建了实例,有时候可能会造成不必要的资源浪费。

注意:

在实际应用中,单例模式需要谨慎使用,特别是在需要考虑可维护性、可测试性和代码复用性的情况下。在大多数情况下,推荐使用依赖注入和模块化的方式来处理相关的功能,以便更好地管理和组织代码。但在某些特定场景下,单例模式仍然有其存在的合理性和必要性。

四、常见的单例模式应用场景

JavaScript 中常见的单例模式应用场景有很多,下面举几个例子进行详细分析:

4.1 日志记录器(Logger)

在大多数应用程序中,都需要进行日志记录,而日志记录通常是一个全局共享的功能。使用单例模式可以确保只有一个日志记录器实例存在,并且可以在任何地方方便地调用。

class Logger {constructor() {// 初始化日志记录器}log(message) {// 记录日志}// 其他日志相关方法
}// 单例实例
const logger = new Logger();// 在代码中的任何地方调用
logger.log("This is a log message.");

4.2 配置管理器(Config Manager)

在大型应用程序中,通常需要集中管理配置信息,以便在不同组件和模块中共享和访问。使用单例模式可以确保只有一个配置管理器实例,并且可以方便地获取和更新配置信息。

class ConfigManager {constructor() {// 初始化配置信息}getConfig(key) {// 获取特定配置项}setConfig(key, value) {// 更新特定配置项}// 其他配置相关方法
}// 单例实例
const configManager = new ConfigManager();// 在代码中的任何地方获取或更新配置
const config = configManager.getConfig("database");
configManager.setConfig("timeout", 5000);

这些仅展示了使用单例模式的一些常见场景,它们都需要确保只有一个实例对象存在,并且可以在应用的任何地方方便地调用。

单例模式可以简化对共享功能的管理和使用,提高代码的可维护性和可读性。但需要记住,单例模式并不适用于所有场景,需要根据具体的业务需求来判断是否使用。

五、总结

单例模式在合适的场景下可以提供简单有效的解决方案,但需要权衡其优缺点并根据具体需求谨慎使用。合理并适度地使用单例模式可以提高代码的可维护性和可读性,优化应用的性能和资源利用。

  1. 单例模式是一种最常见的设计模式之一,用于确保一个类只有一个实例对象,并且该对象可以在整个应用中被共享和访问。

  2. JavaScript中,可以使用构造函数静态方法闭包等方式来实现单例模式。

  3. 单例模式的优点包括简化代码节省资源方便共享和访问避免全局变量污染等。

  4. 单例模式的缺点包括引入全局状态降低代码的可测试性和可维护性增加耦合度和依赖关系以及潜在的性能问题等。

  5. 在使用单例模式时,需要注意避免滥用过度使用避免引入全局状态、尽量减少对单例对象的直接访问,并且考虑可测试性和可维护性等因素。

这篇关于JS设计模式之“单孑独立” - 单例模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1133143

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>