设计模式 创建型 单例模式(Singleton Pattern)与 常见技术框架应用 解析

在这里插入图片描述

单例模式(Singleton Pattern)是一种创建型设计模式,旨在确保某个类在应用程序的生命周期内只有一个实例,并提供一个全局访问点来获取该实例。这种设计模式在需要控制资源访问、避免频繁创建和销毁对象的场景中尤为有用。

一、核心思想

单例模式的核心思想是限制类的实例化次数,确保整个应用程序中只有一个实例存在,并且这个实例可以被全局访问。这通常通过私有化构造函数、提供一个静态方法来获取实例的方式实现。

  1. 唯一性:保证一个类在系统中只有一个实例。
  2. 控制访问:提供一个全局访问点来获取该实例。
  3. 延迟初始化(可选):实例化可以延迟到第一次使用时,以节省资源。
实现单例模式的关键要素:
  • 私有构造函数:防止外部通过new关键字创建新的实例。
  • 静态方法或属性:用于存储和返回唯一的实例。
  • 线程安全:如果应用是多线程的,则需要确保在并发环境下也能正确工作。

二、定义与结构

定义:单例模式确保一个类只有一个实例,并提供一个全局访问点来获取该实例。

结构

  • 单例类:负责创建和管理唯一的实例。
  • 静态成员变量:用于保存唯一的实例引用。
  • 获取实例方法:通常是一个静态方法,用于返回唯一的实例。
  • 私有构造函数:防止外部通过构造函数创建多个实例。
角色
  • 单例类:包含私有构造函数、静态成员变量和获取实例的静态方法。

三、实现步骤及代码示例

以Java为例,单例模式的实现方式有多种,包括饿汉式、懒汉式、双重检查锁定(Double-Checked Locking)和静态内部类实现方式等。以下是几种常见实现的代码示例:

1、饿汉式

  • 特点:在类加载时就创建实例,没有延迟加载的效果,但避免了多线程的同步问题。
  • 优点:线程安全,执行效率高。
  • 缺点:可能导致内存浪费,因为实例在类加载时就已创建,即使未使用。
public class HungrySingleton implements Serializable {private static final long serialVersionUID = 1L;private static final HungrySingleton hungry = new HungrySingleton();private HungrySingleton() {// 防止反序列化时重新创建实例if (hungry != null) {throw new RuntimeException("请使用 HungrySingleton.getInstance() 方法获取一个单例实例");}}public static HungrySingleton getInstance() {return hungry;}// 其他方法...
}

2、懒汉式(线程不安全)

  • 特点:按需加载,节省资源,只有在确实需要的时候才会创建实例。但存在线程安全问题。

  • 优点:延迟加载,提高了程序启动的速度。

  • 缺点:在多线程环境下需要额外的同步机制来保证线程安全。

  • 线程不安全的懒汉式示例代码:

public class LazySingleton {private static LazySingleton lazyMan;public LazySingleton() {// 构造函数可以为空或包含初始化代码}public static LazySingleton getInstance() {if (lazyMan == null) {lazyMan = new LazySingleton();}return lazyMan;}// 其他方法...
}

上述代码在多线程环境下可能会出现多个实例,因此线程不安全。

注意:懒汉式(线程不安全)在多线程环境下可能会导致多个实例被创建,因此通常不推荐使用。

3、双重检查锁定(Double-Checked Locking)

线程安全的懒汉式示例代码(双重检查锁定):

public class LazySafe {private static volatile LazySafe instance = null;private LazySafe() {}public static LazySafe getInstance() {if (instance == null) {synchronized (LazySafe.class) {if (instance == null) {instance = new LazySafe();}}}return instance;}
}

使用volatile关键字确保在多线程环境中正确处理,双重检查锁定保证了线程安全和性能。

4、静态内部类实现方式

  • 特点:利用Java的类加载机制实现延迟加载,线程安全且高效。

  • 优点:实现简单,无需额外的同步机制。

  • 缺点:无法支持非静态单例需求。

  • 示例代码:

public class InnerClassSingleton {private InnerClassSingleton() {// 构造函数可以为空或包含初始化代码}private static class Holder {private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();}public static InnerClassSingleton getInstance() {return Holder.INSTANCE;}// 其他方法...
}

5、枚举单例

  • 特点:实现简单,线程安全,防止反射和序列化破坏。

  • 优点:最简洁的实现方式,由Java语言本身保证线程安全性。

  • 缺点:不支持延迟加载。

  • 示例代码:

public enum Singleton {INSTANCE;public void someMethod() {// 单例方法逻辑}
}

四、JavaScript中的单例模式实现

基本实现

class Singleton {constructor() {if (typeof Singleton.instance === 'object') {return Singleton.instance;}Singleton.instance = this;}static getInstance() {if (!this.instance) {new this();}return this.instance;}someBusinessLogic() {// ...业务逻辑...}
}// 使用示例
const instanceA = Singleton.getInstance();
const instanceB = Singleton.getInstance();console.log(instanceA === instanceB); // true

模块模式下的单例

在JavaScript中,模块本身就是一个天然的单例,因为每个模块只会被加载一次。因此,可以利用ES6模块来实现单例模式。

// singleton.js
const singleton = (() => {let privateState = {}; // 私有状态function somePrivateMethod() {// 私有方法}return {publicMethod: function() {// 公共方法somePrivateMethod();},getPrivateState: function() {return privateState;}};
})();export default singleton;// 在其他文件中导入并使用
import singleton from './singleton';singleton.publicMethod();
console.log(singleton.getPrivateState());

线程安全的单例(适用于Node.js)

当涉及到多线程环境时,如Node.js worker_threads,可能需要确保线程安全。

class ThreadSafeSingleton {constructor() {if (!ThreadSafeSingleton.instance) {ThreadSafeSingleton.instance = this;}return ThreadSafeSingleton.instance;}static getInstance() {if (!this.instance) {// 如果是在多线程环境中,这里应该加入锁机制// 例如使用Promise或其他同步机制来保证线程安全new this();}return this.instance;}someBusinessLogic() {// ...业务逻辑...}
}

使用立即执行函数表达式(IIFE)

这是一种经典的JavaScript单例实现方式,尤其是在不支持模块化的旧版本浏览器中。

const singleton = (function () {const privateState = {}; // 私有状态function privateMethod() {// 私有方法}return {publicMethod: function () {// 公共方法privateMethod();},getPrivateState: function () {return privateState;}};
})();

五、常见技术框架应用

在Spring框架中,单例模式也得到了广泛应用。Spring容器默认创建的Bean是单例的,即在整个Spring IoC容器中,一个Bean只会有一个实例。以下是Spring中配置单例Bean的示例:

<bean id="myBean" class="com.example.MyBean" singleton="true"/>

或者,在基于注解的配置中,可以通过@Component@Bean注解来定义Bean,并默认其为单例:

@Component
public class MyBean {// ...
}@Configuration
public class AppConfig {@Beanpublic MyBean myBean() {return new MyBean();}
}

六、应用场景

单例模式常用于以下场景:

  1. 日志记录器:在整个应用程序中,通常只需要一个日志记录器来记录日志信息。
  2. 配置管理器:应用程序的配置信息通常只需要一个实例来管理,以确保配置的一致性。
  3. 数据库连接池:为了有效地管理数据库连接,避免频繁地创建和销毁连接,通常使用单例模式来创建数据库连接池。
  4. 线程池:管理和复用线程,避免频繁地创建和销毁线程,提高系统性能。
  5. 全局计数器:在需要全局唯一的计数器时,可以使用单例模式。
  6. 购物车服务:在电子商务网站中,用户的购物车应当是唯一的。
  7. 窗口管理器:图形界面程序中,窗口管理器应确保只有一个实例来协调所有窗口的行为。

七、优缺点

优点

  1. 延迟加载:只有在需要时才创建实例,节省资源。
  2. 全局访问点:提供一个全局访问对象的方式,方便在不同模块和组件之间共享资源。
  3. 控制资源:在需要限制实例数量的场景下(如数据库连接池、日志系统),单例模式能够确保系统中只有一个实例在操作资源。

缺点

  1. 线程安全问题:在多线程环境下,需要额外的同步机制来确保线程安全,可能会影响性能。
  2. 单例类的职责单一:单例模式通常要求单例类只承担一个职责,否则可能会违背单一职责原则,导致代码难以维护。

综上所述,单例模式是一种非常有用的设计模式,在需要控制资源访问和避免频繁创建对象的场景中发挥着重要作用。然而,在使用时也需要注意其潜在的缺点,并根据具体场景选择合适的实现方式。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Xsens动捕与人形机器人训练》讲座将于1月9日下午2:30在线上召开

《Xsens动捕与人形机器人训练》讲座将于1月9日下午2:30在线上召开&#xff0c;本次讲座中来自Xsens的人形机器人与动捕技术专家Jeffrey Muller与Dennis Kloppenburg不仅将就Xsens动作捕捉系统与人形机器人行为训练中的实际应用进行详细讲解&#xff0c;同时还会对目前大家所关注…

Flutter踩坑记-第三方SDK不兼容Gradle 8.0,需适配namespace

最近需要集成Flutter作为Module&#xff0c;Flutter依赖了第三方库&#xff0c;Gradle是8.0版本。 编译报错&#xff1a; 解决办法是在.android根目录下的build.gradle下新增一行代码&#xff1a; buildscript {ext.kotlin_version "1.8.22"repositories {google()…

Linux驱动开发学习准备(Linux内核源码添加到工程-Workspace)

Linux内核源码添加到VsCode工程 下载Linux-4.9.88源码&#xff1a; 没有处理同名文件的压缩包&#xff1a; https://pan.baidu.com/s/1yjIBXmxG9pwP0aOhW8VAVQ?pwde9cv 已把同名文件中以大写命名的文件加上_2后缀的压缩包&#xff1a; https://pan.baidu.com/s/1RIRRUllYFn2…

ImageNet 2.0?自动驾驶数据集迎来自动标注新时代

引言&#xff1a; 3DGS因其渲染速度快和高质量的新视角合成而备受关注。一些研究人员尝试将3DGS应用于驾驶场景的重建。然而&#xff0c;这些方法通常依赖于多种数据类型&#xff0c;如深度图、3D框和移动物体的轨迹。此外&#xff0c;合成图像缺乏标注也限制了其在下游任务中的…

朱姆沃尔特隐身战舰:从失败到威慑

前言 "朱姆沃尔特"号驱逐舰是美国海军雄心勃勃的项目&#xff0c;旨在重塑未来海战。它融合了隐身、自动化和强大火力&#xff0c;然而由于技术问题和预算超支&#xff0c;原计划建造32艘的目标被大幅缩减&#xff0c;最终只建造了三艘。该舰的设计特点包括“穿浪逆船…

电子电器框架 --- 电动汽车上的车载充电器(OBC)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

【C语言的小角落】--- 深度理解取余/取模运算

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; C语言的小角落 本篇博客我们来深度理解取余/取模&#xff0c;以及它们在不同语言中出现不同现象的原因。 &#x1f3e0; 关于取整 &#x1f3b5; 向0取整…

快速上手LangChain(三)构建检索增强生成(RAG)应用

文章目录 快速上手LangChain(三)构建检索增强生成(RAG)应用概述索引阿里嵌入模型 Embedding检索和生成RAG应用(demo:根据我的博客主页,分析一下我的技术栈)快速上手LangChain(三)构建检索增强生成(RAG)应用 langchain官方文档:https://python.langchain.ac.cn/do…

Spring源码分析之事件机制——观察者模式(二)

目录 获取监听器的入口方法 实际检索监听器的核心方法 监听器类型检查方法 监听器的注册过程 监听器的存储结构 过程总结 Spring源码分析之事件机制——观察者模式&#xff08;一&#xff09;-CSDN博客 Spring源码分析之事件机制——观察者模式&#xff08;二&#xff…

redux react-redux @reduxjs/toolkit

redux团队先后推出了redux、react-redux、reduxjs/toolkit&#xff0c;这三个库的api各有不同。本篇文章就来梳理一下当我们需要在项目中集成redux&#xff0c;从直接使用redux&#xff0c;到使用react-redux&#xff0c;再到react-redux和reduxjs/toolkit配合使用&#xff0c;…

OpenHarmony通过挂载镜像来修改镜像内容,RK3566鸿蒙开发板演示

在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容&#xff0c;修改源码再编译很费时。今天为大家介绍一个便捷的方法&#xff0c;让OpenHarmony通过挂载镜像来修改镜像内容&#xff01;触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器&#xff0c;树…

网安数学基础期末复习

目录 整除同余同余方程群和环 整除 a的显然因数/平凡因数1&#xff0c;a整除的传递性和组合性 若 a ∣ b , b ∣ a a|b,b|a a∣b,b∣a 则 a b a\pm b ab欧几里得带余除法 公因数和最大公因数在整除里的定义&#xff0c;最大公因数为1则两数互质&#xff0c;注意公因数有正…

NSGA-II(非支配排序遗传算法II)详解与实现

NSGA-II(非支配排序遗传算法II)详解与实现 1. 算法简介 NSGA-II(Non-dominated Sorting Genetic Algorithm II)是一种高效的多目标优化算法&#xff0c;由Deb等人在2002年提出。它主要解决多个目标之间相互冲突的优化问题。 1.1 核心特点 快速非支配排序 时间复杂度&#xf…

Fabric环境部署

官方下载文档&#xff1a;A Blockchain Platform for the Enterprise — Hyperledger Fabric Docs main documentation 1.1 创建工作目录 将Fabric代码按照GO语言的推荐方式进行存放&#xff0c;创建目录结构并切换到该目录下。具体命令如下&#xff1a; mkdir -p ~/go/src/g…

回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测

回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测预测效果基本介绍模型架构程序设计参考资料 预测效果 基本介绍 CNN-SVM多输入单输出回归预测是一种结合卷积神经网络&#xff08;CNN&#xff09;和支持向量机&#…

SOLIDWORKS Composer在产品设计、制造与销售中的应用

SOLIDWORKS Composer是一款专为技术团队设计的高效沟通工具&#xff0c;广泛应用于产品设计、制造、销售及售后等领域。它能从复杂的CAD数据中提取关键信息&#xff0c;轻松转化为高质量的产品文档、交互式3D动画及说明视频&#xff0c;显著提升产品沟通效率。 Composer擅长制…

【数据结构Ⅰ复习题】

如有错误欢迎指正&#xff0c;题目根据教材----------严蔚敏数据结构&#xff08;c语言版 第2版&#xff09;人民邮电电子版 数据结构Ⅰ复习题 一、填空题1&#xff0e;算法应该具备的5个重要特性有___有穷性___、确定性、可行性、输入和输出。2&#xff0e;非空单链表L中*p是头…

flutter 专题二十四 Flutter 响应式状态管理框架GetX

一、状态管理框架对比 在Flutter的状态管理框架中&#xff0c;主流的状态管理框架有四个&#xff1a;GetX&#xff08;又称为Get&#xff09;、BLoC、MobX、Provider。 Provider 其中&#xff0c;Provider是Flutter社区提供的一种状态管理工具&#xff0c;本质上是对Inherit…

禁用div的写法(自定义disabled)Vue3

因为div 元素本身没有 disabled 属性&#xff0c;所以需要根据JavaScript中的变量、通过动态绑定 class &#xff08;Vue的:class&#xff09;来改变样式。 需要一个变量 isDivDisabled import { ref } from vue; let isDivDisabled ref(false);当 isDivDisabled true &…

大模型系列——旋转位置编码和长度外推

绝对位置编码 旋转位置编码 论文中有个很直观的图片展示了旋转变换的过程&#xff1a; 对于“我”对应的d维向量&#xff0c; 拆分成d/2组以后&#xff0c;每组对应一个角度&#xff0c;若1对应的向量为(x1,x2)&#xff0c;应用旋转位置编码&#xff0c;相当于这个分量旋转了m…