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

news2024/9/22 21:18:04

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2100107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud开发实战(一):搭建SpringCloud框架

本系列文章主要是记录在工作中用到的微服务的各个组件,以及学习新的微服务组件~如有问题,欢迎大家批评指导。如果本文对你有帮助,还请点个收藏和关注。感谢支持,希望大家写的代码都没有BUG!! 前言 下面是我…

Linux下编译安装SuperLU

SuperLU用于求解大规模稀疏线性方程组,本文记录在远程Linux服务器下编译安装SuperLU的流程。 一、配置VS Code 2.1 安装VS Code Extensions 在本地打开VS Code, 安装以下扩展插件, Task Explorer Output Colorizer Git Extension Pack Remote Develop…

Stirling-PDF:基于Web的开源PDF处理工具

PDF文件进行各种各样的操作,比如合并、拆分、加密、解密、旋转、压缩等等,功能超全,而且开源免费,简直是神器! GitHub - Stirling-Tools/Stirling-PDF: #1 Locally hosted web application that allows you to perfor…

【JAVA开源】基于Vue和SpringBoot的历史学习网站

本文项目编号 T 004 ,文末自助获取源码 \color{red}{T004,文末自助获取源码} T004,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

IDEA主题的设置

目录 一、更换皮肤: 二、设置背景图片: 1.点击 File -> Settings ; 2.选择 Appearance & Behavior -> Appearance ; 一、更换皮肤: 1. Theme: 点击下拉框打开; 白色皮肤: inteIIiJ light Windows 10 Lig…

VirtualLab Fusion Installer-7.6.1.18 安装包 永不过期 永久使用 下载

下载地址(资源制作整理不易,下载使用需付费,不能接受请勿浪费时间下载) 链接:https://pan.baidu.com/s/14yJGZAosK_ftJhHD0D4VHA?pwd00zn 提取码:00zn

Lua:条件断点

如果有很多方式都要经过这个函数,但是你只需要满足其中例如参数等于Test的这一种,可以在断点处右键点击编辑断点打上条件断点,只有参数EventName等于Test的才会断上。

如何打造高校实验室预约系统?Java SpringBoot助力高效管理,MySQL存储数据,Vue前端展现,四步实现学生轻松预约!

🍊作者:计算机毕设匠心工作室 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目…

【机器学习-神经网络】循环神经网络

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…

Graylog配置用户权限以及常用搜索语法

文章目录 一、Graylog配置用户管理1、用户创建2、角色权限管理 二、搜索语法 基于Docker搭建Graylog的具体步骤: https://blog.csdn.net/weixin_44876263/article/details/141638739?spm1001.2014.3001.5502 一、Graylog配置用户管理 1、用户创建 2、角色权限管理…

Linux--实现简易shell

文章目录 shell定义和功能myshell.cGetCwd()GetUsrName()GetHostName()MakeCommandLineAndPrint()GetUserCommand()SplitCommand()Die()ExecuteCommand()GetHome()Cd()CheckBuildin()CheckRedir()myshell.c完整代码 makefile测试函数和进程之间的相似性 Shell是一个功能强大的工…

LVS之net模式实验

总结: lvs #配置环境,两个网卡 [rootlvs ~]# cd /etc/NetworkManager/system-connections/ [rootlvs system-connections]# ls ens160.nmconnection eth0.nmconnection eth1.nmconnection [rootlvs system-connections]# vim eth0.nmconnection [co…

华为OD机试 - 猜数字 - 穷举搜索(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(E卷D卷A卷B卷C卷)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加…

【RabbitMQ之一:windows环境下安装RabbitMQ】

目录 一、下载并安装Erlang1、下载Erlang2、安装Erlang3、配置环境变量4、验证erlang是否安装成功 二、下载并安装RabbitMQ1、下载RabbitMQ2、安装RabbitMQ3、配置环境变量4、验证RabbitMQ是否安装成功5、启动RabbitMQ服务(安装后服务默认自启动) 三、安…

Vue2转Vue3学习历程

选项式API>组合式API vue3和vue2的差别就是选项式api改为组件式api,就是以前vue2要定义data、method、mounted,在vue3就变为了更模块化的,并且我感觉vue3设计思路更多是以调用方法的方式实现,比如我实现一个方法,并…

C语言深入理解指针2

1.数组名的理解 #include <stdio.h> int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] %p\n", &arr[0]);printf("arr %p\n", arr);return 0; }可以发现数组名和数组首元素地址的打印结果一样&#xff0c;因此&#xf…

研究生深度学习入门的十天学习计划------第七天

第7天&#xff1a;自然语言处理&#xff08;NLP&#xff09;中的深度学习 目标&#xff1a; 掌握自然语言处理的基础知识与深度学习模型&#xff0c;理解如何应用RNN、LSTM、Transformer等模型处理文本数据。 7.1 自然语言处理的基础概念 自然语言处理&#xff08;NLP&#…

Vue学习笔记 二

4、Vue基础扩展 4.1 插槽 组件的最大特性就是复用性,而用好插槽能大大提高组件的可复用能力在Vue中插槽是很重要的存在,通过插槽,我们可以把父组件中指定的DOM作用到子组件的任意位置,后面我们坐项目用到的组件库比如element-ui,vant-ui都频繁用到的插槽,Vue的插槽主要有…

【hot100篇-python刷题记录】【在排序数组中查找元素的第一个和最后一个位置】

R7-二分查找篇 目录 双指针 二分优化 ps: 思路&#xff1a; 双指针 直接用双指针回缩啊 class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:ret[-1,-1]left,right0,len(nums)-1while left<len(nums):if nums[left]target:ret[0]…

可解释性与公平性的关系

可解释模型更有可能公平的三个原因 可解释性和公平性似乎是相辅相成的。可解释性涉及理解模型如何进行预测。公平性涉及理解预测是否偏向某些群体。负责任的人工智能框架和机器学习会议始终将这两个特征一起提及。然而&#xff0c;可解释性并不一定意味着公平。 话虽如此&…