当前位置: 首页 > news >正文

Java设计模式—单例模式(Singleton Pattern)

目录

一、定义 

二、应用场景 

三、具体实现

示例一

示例二

四、懒汉与饿汉

饿汉模式

懒汉模式

五、总结

六、说明


一、定义 

二、应用场景 

‌单例模式的应用场景主要包括以下几个方面:

  1. ‌日志系统:在应用程序中,通常只需要一个日志系统,通过单例模式可以避免在多个地方创建多个日志对象,降低资源消耗。‌

  2. ‌数据库连接池:数据库连接池是一个重要的资源,使用单例模式可以确保应用程序中只有一个数据库连接池实例,从而避免资源浪费。

  3. ‌配置文件管理器:为了管理应用程序的配置文件,通常只需要一个配置文件管理器实例。单例模式可以确保整个应用程序中只有一个配置文件管理器实例。

  4. ‌缓存系统:缓存系统是提高应用程序性能的关键组件,使用单例模式可以确保整个应用程序中只有一个缓存实例。

  5. ‌GUI组件:在图形用户界面(GUI)开发中,单例模式可以确保整个应用程序中只有一个GUI组件实例,以保持用户界面的一致性和稳定性。

  6. ‌读取配置信息:如果配置信息需要在程序启动时加载,并且只需读取一次,那么可以使用单例模式来读取配置文件。‌

此外,单例模式还适用于那些创建对象时资源消耗大,但又需要频繁访问该对象的场景,或者需要对系统内的资源进行统一的读写操作的场景,比如进行配置文件的读写操作。‌

总的来说,单例模式通常适用于在整个应用程序中只需要一个实例化对象的场景,以确保资源的高效利用和应用程序的稳定性。

三、具体实现

示例一

“ 需求:对于项目中的 JSON 要格式化处理对象,采用 双检锁单例模式 进行管理,从而复用对象,避免重复创建对象的开销 ”

实现:

创建单例:

import com.fasterxml.jackson.databind.ObjectMapper;// JsonFormatter 类负责管理 ObjectMapper 对象,它是 Jackson 库中用于处理 JSON 的核心类。public class JsonFormatter {private static volatile JsonFormatter instance;private ObjectMapper objectMapper;// 私有构造方法,防止外部实例化private JsonFormatter() {// 初始化 ObjectMapperobjectMapper = new ObjectMapper();// 可以在这里配置 ObjectMapper 的特性,例如日期格式化、空字段处理等}// 获取单例实例的静态方法
// 使用双检锁(double-checked locking)来确保在多线程环境下只创建一个 JsonFormatter 实例。public static JsonFormatter getInstance() {if (instance == null) {
//volatile 关键字确保在多线程环境中正确地处理 instance 变量,防止指令重排序带来的问题。synchronized (JsonFormatter.class) {if (instance == null) {instance = new JsonFormatter();}}}return instance;}// 提供了一个公共方法来格式化 JSON 字符串,可以将对象转换为 JSON 格式的字符串。public String formatJson(Object obj) {try {return objectMapper.writeValueAsString(obj);} catch (Exception e) {e.printStackTrace();return null;}}
}

 使用单例:

public class MyApp {public static void main(String[] args) {JsonFormatter jsonFormatter = JsonFormatter.getInstance();// 示例对象MyObject obj = new MyObject("John Doe", 30);// 格式化为 JSON 字符串String jsonString = jsonFormatter.formatJson(obj);System.out.println("Formatted JSON: " + jsonString);}
}

 

         使用双检锁单例模式来管理 JSON 格式化处理对象,确保在整个项目中只有一个 JsonFormatter 实例存在,避免了重复创建对象的开销,同时提供了一个便捷的方式来操作 JSON 数据的格式化。这种方式非常适合在需要频繁处理 JSON 数据的项目中,可以显著提升性能和资源利用率。

示例二

“需求:通过单例模式可以确保配置信息在整个系统中只有一个实例,避免多次加载配置文件或多次访问数据库”

实现:

创建配置信息类:这个类负责加载和存储配置信息

// ConfigManager.java - 单例模式的配置管理器
// ConfigManager 类可以进一步扩展,例如支持从文件中加载配置、支持动态更新配置、支持不同环境的配置切换等。这样,通过单例模式管理配置信息,能够有效地避免多次加载配置文件或访问数据库,提高系统性能和管理便捷性。public class ConfigManager {private static ConfigManager instance;
//静态单例实例变量,使用 private static 关键字声明了一个静态的 instance 变量,用于保存 ConfigManager 类的唯一实例。private String configFile; // 用于存储配置文件名或配置内容// 私有构造方法,防止外部实例化private ConfigManager() {// 加载配置文件或初始化配置内容this.configFile = "config.properties"; // 示例配置文件名// 实际应用中可以在构造方法中进行配置文件的加载// 例如:this.loadConfig();}// 公有静态方法,获取唯一实例,getInstance() 方法是获取 ConfigManager 类的实例的唯一入口。这个方法使用了双重检查锁定(double-checked locking)来确保在多线程环境下也能保持单例的唯一性和线程安全性。public static ConfigManager getInstance() {if (instance == null) {synchronized (ConfigManager.class) {if (instance == null) {instance = new ConfigManager();}}}return instance;}// 示例方法:获取配置信息public String getConfig() {return this.configFile;}// 示例方法:设置配置信息public void setConfig(String configFile) {this.configFile = configFile;}
}

 实现单例模式:确保在整个应用中只有一个配置信息实例。

public class MyApp {public static void main(String[] args) {ConfigManager configManager = ConfigManager.getInstance();// 获取配置信息示例String configFile = configManager.getConfig();System.out.println("Current config file: " + configFile);// 修改配置信息示例configManager.setConfig("new_config.properties");System.out.println("Updated config file: " + configManager.getConfig());}
}

        整个 ConfigManager 类符合单例模式的要求:它保证了在整个应用程序中只有一个实例存在,并提供了全局访问点来获取这个唯一的实例。这样做可以确保配置信息在整个系统中只有一个实例,避免了多次加载配置文件或多次访问数据库的问题。 

四、懒汉与饿汉

一文搞懂设计模式—单例模式

在选择单例模式的创建方式时,通常可以选择懒汉模式或饿汉模式,具体取决于项目的需求和使用场景。让我们来比较一下懒汉模式和饿汉模式的特点和适用场景:

饿汉模式

在饿汉模式下,实例在类加载时就被创建,因此称为“饿汉”——因为它一开始就“吃饱了”。

特点

  • 线程安全:由于实例在类加载时就创建并初始化,所以不存在多线程环境下的线程安全问题。
  • 简单:实现起来比较简单,没有复杂的同步控制。
  • 性能较好:在访问量较大或者对性能有一定要求的场景下,由于不需要在获取实例时进行同步操作,性能较好。

适用场景

  • 当单例对象的创建和初始化操作比较简单,且在程序运行时就需要频繁使用时,可以考虑使用饿汉模式。
public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {// 私有构造方法}public static Singleton getInstance() {return instance;}
}

懒汉模式

在懒汉模式下,实例在第一次使用时才进行创建,因此称为“懒汉”——直到需要才“吃”。

特点

  • 延迟加载:只有在首次调用 getInstance() 方法时才会创建实例。
  • 线程安全性需要考虑:如果不加同步控制,在多线程环境下可能会创建多个实例。
  • 资源利用率高:只有在需要时才会创建对象,节省了资源。

适用场景

  • 当单例对象的创建和初始化操作较为复杂或者需要延迟加载时,可以考虑使用懒汉模式。
  • 如果应用中频繁使用单例对象的情况不多,懒汉模式可以节省资源。

示例(带双重检查锁定的懒汉模式):

public class Singleton {private static volatile Singleton instance;private Singleton() {// 私有构造方法}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

五、总结

  • 饿汉模式适合在单例对象比较简单,且在程序整个生命周期内需要频繁使用的情况下,可以提升性能。
  • 懒汉模式适合在单例对象创建和初始化较为复杂,或者需要延迟加载的情况下,以节省资源并避免不必要的初始化。

        具体如何选择呢,像示例一中的代码,使用懒汉模式(带双重检查锁定)是比较合适的选择。因为:

  1. 延迟加载:你的 JsonFormatter 类中的 ObjectMapper 实例需要在第一次调用 getInstance() 方法时才被初始化。这种延迟加载的方式可以节省资源,特别是在应用程序启动时,可能不立即需要操作 JSON 的情况下。

  2. 线程安全性:通过双重检查锁定,确保了在多线程环境下只会创建一个 JsonFormatter 实例。这种方式在保证线程安全的同时,又能避免每次调用 getInstance() 都进行同步,提高了性能。

  3. 资源利用:由于 ObjectMapper 可能比较重量级(尤其是在配置了特定的序列化/反序列化规则时),懒汉模式可以避免不必要的对象创建和初始化,从而提高了资源的利用率。

六、说明

日志管理上使用@Slf4j 中的log 这个注解里面没有用到单例模式

相关文章:

Java设计模式—单例模式(Singleton Pattern)

目录 一、定义 二、应用场景 三、具体实现 示例一 示例二 四、懒汉与饿汉 饿汉模式 懒汉模式 五、总结 六、说明 一、定义 二、应用场景 ‌单例模式的应用场景主要包括以下几个方面: ‌日志系统:在应用程序中,通常只需要一个日…...

AV1帧间预测(二):运动补偿

运动补偿(Motion Compensation,MC)是帧间预测最基础的工具,AV1支持两种运动补偿方式,一种是传统的平移运动补偿,另一种是仿射运动补偿。下面分别介绍这两种运动补偿方法。 平移运动补偿 平移运动补偿是最传统的运动补偿方式,H.26…...

数学建模(5)——逻辑回归

一、二分类 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklea…...

【C++高阶】:深入探索C++11

✨ 心似白云常自在,意如流水任东西 🌏 📃个人主页:island1314 🔥个人专栏:C学习 🚀 欢迎关注:👍点赞 &#x1f4…...

6. 自定义Docker镜像

如何自定义Docker镜像:从基础到实践 Docker作为一个容器化平台,使得应用的打包、分发和运行变得更加高效和便捷。本文将详细介绍如何自定义一个Docker镜像,包括镜像的构成、分层原理、创建自定义镜像的具体步骤,并演示如何打包和…...

「12月·长沙」人工智能与网络安全国际学术会议(ISAICS 2024)

人工智能与网络安全国际学术会议(ISAICS 2024)将于2024年12月20日-2024年12月22日在湖南长沙召开。会议中发表的文章将会被收录,并于见刊后提交EI核心索引。会议旨在在为国内与国际学者搭建交流平台,推进不同学科领域的融合发展,就当今人工智能与网络安全范畴内各学…...

【技术支持案例】使用S32K144+NSD8381驱动电子膨胀阀

文章目录 1. 前言2. 问题描述3. 理论分析3.1 NSD8381如何连接电机3.2 S32K144和NSD8381的软件配置 4.测试验证4.1 测试环境4.2 测试效果4.3 测试记录 1. 前言 最近有客户在使用S32K144NSD8381驱动电子膨胀阀时,遇到无法正常驱动电子膨胀阀的情况。因为笔者也是刚开…...

第二期:集成电路(IC)——智能世界的微观建筑大师

嘿,小伙伴们!👋 我是你们的老朋友小竹笋,一名热爱创作和技术的工程师。上一期我们聊了聊AI芯片,这次我们要深入到更微观的层面,来探究集成电路(IC)的世界。准备好一起探索了吗&#…...

基于物联网的区块链算力网络,IGP/BGP协议

目录 基于物联网的区块链算力网络 IGP/BGP协议 IGP(内部网关协议) BGP(边界网关协议) 内部使用ISP的外部使用BGP的原因 一、网络规模和复杂性 二、路由协议的特性 三、满足业务需求 四、结论 基于物联网的区块链算力网络 通 过 多个物联网传感器将本地计算…...

每日一题~960 div2 A+B+C(简单奇偶博弈,构造,观察性质算贡献)

A题意: N 长的数组。 一次操作: 最开始的mx 为零。 选出一个数(使得这个数>mx) ,之后将mx 更新为这个数,将这个数置为零。 不能做这个操作的,输。 问是否有先手赢的策略。有的话,输出yes 否则no 当时一…...

音视频入门基础:H.264专题(17)——FFmpeg源码获取H.264裸流文件信息(视频压缩编码格式、色彩格式、视频分辨率、帧率)的总流程

音视频入门基础:H.264专题系列文章: 音视频入门基础:H.264专题(1)——H.264官方文档下载 音视频入门基础:H.264专题(2)——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…...

Aboboo一些操作

常用快捷键⌨ 快捷键/操作方式 功能 鼠标中键/Esc 进入/退出全屏 空格/Tab 暂停/恢复播放 左/右箭头 快退/快进 Ctrl-左/右箭头 30秒快退/快进 Alt-左/右箭头 60秒快退/快进 Ctrl-Alt-左/右箭头 播放速率调节 PageUp/PageDown 上一句/下一句 上下箭头/滚轮 …...

获取行号LineNumberReader

(每日持续更新)jdk api之LineNumberReader基础、应用、实战-CSDN博客...

python数据结构与算法

0.时间复杂度和空间复杂度 快速判断算法时间复杂度:算法运行时间 1.确定问题规模n 2.循环减半 logn 3.k层关于n的循环 n^k 空间复杂度:评估算法内存占用大小 使用几个变量 O(1) 使用长度为n的一维列表 O(n&#xff09…...

大数据学习之Flink基础(补充)

Flink基础 1、系统时间与事件时间 系统时间(处理时间) 在Sparksreaming的任务计算时,使用的是系统时间。 假设所用窗口为滚动窗口,大小为5分钟。那么每五分钟,都会对接收的数据进行提交任务. 但是,这里有…...

C++基础语法:友元

前言 "打牢基础,万事不愁" .C的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结. 以<C Prime Plus> 6th Edition(以下称"本书")的内容开展学习 引入 友元提供了一种特别的方式,访问对象私有数据. 友元有三…...

【大模型系列】Video-LaVIT(2024.06)

Paper&#xff1a;https://arxiv.org/abs/2402.03161Github&#xff1a;https://video-lavit.github.io/Title&#xff1a;Video-LaVIT: Unified Video-Language Pre-training with Decoupled Visual-Motional TokenizationAuthor&#xff1a;Yang Jin&#xff0c; 北大&#x…...

【总结】nacos作为注册中心-应用启动失败:NacosDiscoveryProperties{serverAddr=‘127.0.0.1:8848‘……

问题现象 启动springboot应用时报错&#xff0c;能够读取到nacos配置&#xff0c;但是使用nacos作为注册中心&#xff0c;应用注册到nacos失败。 应用配置bootstrap.properties如下&#xff1a; # 应用编码&#xff0c;安装时替换变量 spring.application.namedata-center #…...

C语言——数组和排序

C语言——数组和排序 数组数组的概念数组的初始化数组的特点 排序选择排序冒泡排序插入排序 二分查找 数组 数组的概念 数组是一组数据 &#xff1b; 数组是一组相同类型的数据或变量的集合 &#xff1b; 应用场景&#xff1a; 用于批量的处理多个数据 &#xff1b; 语法&…...

QEMU 新增QMPHMP指令【原文阅读】

文章目录 0x0 QEMU原文0x10x11 How to write monitor commands0x12 Overview0x13 Testing 0x20x21 Writing a simple command: hello-world0x22 Arguments 0x30x31 Implementing the HMP command 0x40x41 Writing more complex commands0x42 Modelling data in QAPI0x43 User D…...

用 jose 正确实现 JWT 签发、验签与密钥轮换

1. 为什么你写的 JWT 总是“看起来能用&#xff0c;上线就出事”JWT&#xff08;JSON Web Token&#xff09;这东西&#xff0c;我第一次在项目里用的时候&#xff0c;也是照着文档抄了三行代码&#xff1a;jwt.sign(payload, secret)、jwt.verify(token, secret)、res.json({ …...

2026年想在成都装中央空调?哪家安装质保好这里有答案!

家人们&#xff0c;2026年了&#xff0c;在成都想要装中央空调的小伙伴看过来&#xff01;我作为一个在中央空调领域摸爬滚打多年的真实体验者&#xff0c;深知大家在选择空调时的纠结和痛点。就拿成都的气候来说&#xff0c;夏天闷热&#xff0c;空调得使劲儿制冷&#xff1b;…...

不只是打驱动:深入解读Intel Arc显卡在Linux下的RBAR技术及其对AI性能的实际影响

深入解析Intel Arc显卡RBAR技术&#xff1a;Linux环境下的AI性能优化实践 当一块Intel Arc显卡插入Linux工作站时&#xff0c;大多数用户的第一反应是寻找驱动安装指南。但真正影响AI推理性能的关键&#xff0c;往往隐藏在PCIe总线的一个名为RBAR&#xff08;Resizable Base Ad…...

保姆级教程:用vsomeip实现一个简单的车内服务发现与通信(附C++代码)

车载通信实战&#xff1a;基于vsomeip的服务发现与消息交互全流程解析 在智能座舱与自动驾驶技术快速迭代的今天&#xff0c;车载电子控制单元&#xff08;ECU&#xff09;间的可靠通信成为系统设计的核心挑战。SOME/IP作为汽车电子领域广泛采用的通信协议&#xff0c;其开源实…...

初创团队如何利用Taotoken以最小成本试用多款大模型

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 初创团队如何利用Taotoken以最小成本试用多款大模型 对于初创团队和独立开发者而言&#xff0c;在技术选型与原型验证阶段&#xf…...

告别应用层延时!在迅为RK3568开发板上,将RS485收发切换彻底交给Linux内核驱动

告别应用层延时&#xff01;在迅为RK3568开发板上将RS485收发切换彻底交给Linux内核驱动 工业自动化领域对通信实时性的要求近乎苛刻&#xff0c;当RS485总线上挂载的多个设备响应时间参差不齐时&#xff0c;应用层手动控制的收发切换就像用机械表校准原子钟——看似可行实则漏…...

高通8650 AudioReach实战:手把手调试GSL-Passthru-GPR数据流(附动态调试脚本)

高通8650 AudioReach实战&#xff1a;GSL-Passthru-GPR数据流调试全指南 当你在深夜的实验室里盯着示波器上那条毫无波动的音频信号线时&#xff0c;手机突然响起一阵刺耳的电流噪声——这可能是每位音频驱动工程师都经历过的噩梦时刻。高通AudioReach架构作为现代移动音频系统…...

常用shell命令总结(Linux命令)

当前目录 .上一级目录 …根目录&#xff0c;或者是目录拼接符 /管道符&#xff08;左侧输出作为右侧输入&#xff09; |上一个命令的返回码 $?或 ||且 &&cat 查看文档 cat XX.txt加权限 chmod x 文件 chmod 777 文件改变文件的所有者 chown newowner file.txt改变文件…...

HCIP-Datacom Core Technology V1.0_18 IGMP原理与配置

IGMP用于接收者和直连组播路由之间&#xff0c;建立和维护组播成员关系的组播协议&#xff0c;本章课程将介绍IGMP的原理&#xff0c;以及它不同版本的区别&#xff0c;还有一些其它特性。IGMP介绍组播网络的转发困境正常情况下&#xff0c;组播源将组播报文推送给第一跳路由器…...

利用Taotoken用量看板与成本管理功能精细化控制AI支出

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 利用Taotoken用量看板与成本管理功能精细化控制AI支出 作为团队的技术负责人&#xff0c;在引入大模型能力支持多个研发项目时&…...