独一无二的设计模式——单例模式(Java实现)

1. 引言

亲爱的读者们,欢迎来到我们的设计模式专题,今天的讲解的设计模式,还是单例模式哦!上次讲解的单例模式是基于Python实现(独一无二的设计模式——单例模式(python实现))的,但是目前很多实际系统是通过JAVA实现的,所以今天聊一聊基于JAVA的语言特性,单例模式的实现和应用。

2. 什么是单例模式

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。就像世界上只有一个太阳,我们也希望某些对象在整个应用程序中只有一个实例。单例模式适用于需要全局唯一访问的资源,如数据库连接、配置管理器、日志记录器等。

3. 单例模式的实现(Java)

基本实现

在Java中,单例模式通常使用懒汉式或饿汉式实现,以下讲解四种主要的实现方法:

懒汉式实现,懒汉式单例模式只有在第一次调用getInstance方法时才会创建实例:
public class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}
详细代码解析
  • instance静态变量用于存储单例实例,在类加载时,它被初始化为null
  • getInstance方法是获取实例的关键,如果instance为空,则创建一个新的实例并返回,否则返回已有的实例;
  • 私有构造函数Singleton()防止类被外部实例化,确保实例只能通过getInstance方法获取。
多线程安全的懒汉式实现,为了应对多线程环境,可以使用同步块来确保线程安全:
public class Singleton {private static Singleton instance;private static final Object lock = new Object();private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (lock) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
详细代码解析
  • lock是一个同步对象,用于确保在多线程环境下,只有一个线程能够创建实例;
  • getInstance方法中使用synchronized块来加锁,确保只有一个线程能够进入创建实例的代码块。
饿汉式实现,饿汉式单例在类加载时就创建实例,相比懒汉式避免了多线程问题:
public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}
详细代码解析
  • instance静态变量在类加载时即被初始化,确保实例的唯一性和线程安全;
  • 私有构造函数防止外部实例化。
静态内部类实现,这种方法利用类加载机制,只有在调用getInstance时才会创建实例,确保线程安全和延迟加载:
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}
详细代码解析
  • SingletonHolder是一个静态内部类,包含了Singleton的唯一实例;
  • getInstance方法中返回SingletonHolder.INSTANCE,确保实例的延迟加载和线程安全。

4. 单例模式的应用场景和实例

示例一:配置文件管理

在应用程序中,配置文件通常需要全局访问且不应被重复加载。使用单例模式可以确保配置管理器只有一个实例,从而避免重复加载配置文件。

import java.util.Properties;public class ConfigurationManager {private static ConfigurationManager instance;private Properties config;private ConfigurationManager() {config = new Properties();}public static ConfigurationManager getInstance() {if (instance == null) {instance = new ConfigurationManager();}return instance;}public void setConfig(String key, String value) {config.setProperty(key, value);}public String getConfig(String key) {return config.getProperty(key);}
}

使用示例:

ConfigurationManager configManager = ConfigurationManager.getInstance();
configManager.setConfig("api_url", "https://api.example.com");
System.out.println(configManager.getConfig("api_url"));
示例二:日志记录

日志记录器是单例模式的经典应用之一,通过确保日志记录器的唯一性,我们可以统一管理日志输出,避免多个日志实例之间的混乱:

import java.util.logging.*;public class LoggerSingleton {private static LoggerSingleton instance;private Logger logger;private LoggerSingleton() {logger = Logger.getLogger("singleton_logger");ConsoleHandler handler = new ConsoleHandler();SimpleFormatter formatter = new SimpleFormatter();handler.setFormatter(formatter);logger.addHandler(handler);logger.setLevel(Level.INFO);}public static LoggerSingleton getInstance() {if (instance == null) {instance = new LoggerSingleton();}return instance;}public void log(String message) {logger.info(message);}
}

使用示例:

LoggerSingleton logger = LoggerSingleton.getInstance();
logger.log("This is a log message.");

5. 单例模式的优缺点

优点
  • 控制实例数量:确保一个类只有一个实例,节省资源;
  • 全局访问点:提供一个全局访问点,方便管理和使用。
缺点
  • 不易扩展:由于单例模式限制了实例的数量,可能不利于扩展;
  • 隐藏依赖关系:单例模式通过全局访问点使用实例,可能导致代码依赖关系不明确,不利于测试。

6. 图示

  • 单例模式的UML图:
+----------------+
|   Singleton    |
+----------------+
| - _instance    |
| - _lock        |
+----------------+
| + getInstance()|
+----------------+
  • 单例模式的示意图:

7. 总结

单例模式是一种简单而强大的设计模式,确保一个类只有一个实例,并提供全局访问点。在实际开发中,单例模式广泛应用于配置管理、日志记录等场景,通过合理地使用单例模式,我们可以有效管理和优化资源,确保系统的一致性和稳定性。

希望今天的分享能让大家对单例模式有更深入的理解,如果你在项目中也使用了单例模式,欢迎留言分享你的经验和见解!
在这里插入图片描述

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

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

相关文章

[leetcode]squares-of-a-sorted-array. 有序数组的平方

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int n nums.size();vector<int> ans(n);for (int i 0, j n - 1, pos n - 1; i < j;) {if (nums[i] * nums[i] > nums[j] *…

春秋云境:CVE-2022-25411[漏洞复现]

根据题目提示和CNNVD优先寻找后台管理地址 靶机启动后&#xff0c;使用AWVS进行扫描查看网站结构 在这里可以看到后台管理的登录地址&#xff1a;/admin/&#xff0c;根据题目提示可知是弱口令 尝试admin、123456、admin666、admin123、admin888...等等常见弱口令 正确的账户…

java笔记(30)——反射的 API 及其 使用

文章目录 反射1. 什么是反射2. 获取class字段&#xff08;字节码文件对象&#xff09;方式1方式2方式3应用 3. 获取构造方法和权限修饰符前期准备获取所有的公共构造方法获取所有的构造方法获取无参构造方法获取一个参数的构造方法获取一个参数的构造方法获取两个参数的构造方法…

【日常记录】【JS】SSE 流式传输 ChatGPT 的网络传输模式

文章目录 1、SSE 流式传输2、后端代码3、前端代码5、SSE和WS 对比6、chatgpt SSE的服务端返回的数据参考链接 单工通信是一种单向的通信方式&#xff0c;其中信息只能从发送端传输到接收端&#xff0c;而接收端不能向发送端发送任何信息。在Web开发中&#xff0c;Server-Sent E…

FL Studio 21 中文版分享(内含破解补丁)不是标题党

不知道为什么现在钓鱼的这么多&#xff08;有答案的请在评论区上告诉我&#xff09;&#xff0c;就一个学习版的编曲软件有必要这样子搞吗&#xff1f;我也是在各类博客上找了一大堆教程&#xff0c;根本没几个能用的&#xff0c;索性直接到兔八哥爱分享上找了一个&#xff0c;…

C程序设计谭浩强第五版

程序习题 第一章1、第5题2、第6题 第三章1、第2题2、第2题3、第3题4、第4题Tips 第一章 1、第5题 编写一个C程序,运行时输出以下图形: #include <stdio.h> int main() {for (int i 0; i < 4; i) // 输出4行循环控制{for (int j 0; j < i; j) //第几行就输出几…

【TB作品】玩具电子琴,ATMEGA128单片机,Proteus仿真

题目 7 &#xff1a;玩具电子琴 基于单片机设计一能够发出中音八个音阶的音乐信号的电子琴&#xff0c;能够实现弹奏和音符显示功 能。 具有 8 个音阶按键&#xff0c;每按下一个按键时&#xff0c;所对应的 LED 点亮&#xff0c;音符进行显示。 具体要求如下&#xff1a; &…

PV操作经典例题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文☀️☀️☀️1.水果问题2.和尚打水问题3.餐厅职员问题4.汽车站点问题5.观察者-报告者问题6..阅览室问题 …

DEBOPIE框架:打造最好的ChatGPT交易机器人

本文介绍了如何利用 DEBOPIE 框架并基于 ChatGPT 创建高效交易机器人&#xff0c;并强调了在使用 AI 辅助交易时需要注意的限制以及操作步骤。原文: Build the Best ChatGPT Trading Bots with my “DEBOPIE” Framework 如今有大量文章介绍如何通过 ChatGPT 帮助决定如何以及在…

win10修改远程桌面端口,Windows 10下修改远程桌面端口及服务器关闭445端口的操作指南

Windows 10下修改远程桌面端口及服务器关闭445端口的操作指南 一、修改Windows 10远程桌面端口 在Windows 10系统中&#xff0c;远程桌面连接默认使用3389端口。为了安全起见&#xff0c;建议修改此端口以减少潜在的安全风险。以下是修改远程桌面端口的步骤&#xff1a; 1. 打…

任务调度器——任务切换

一、开启任务调度器 函数原型&#xff1a; void vTaskStartScheduler( void ) 作用&#xff1a;用于启动任务调度器&#xff0c;任务调度器启动后&#xff0c; FreeRTOS 便会开始进行任务调度 内部实现机制&#xff08;以动态创建为例&#xff09;&#xff1a; &#xff0…

web学习笔记(七十二)

目录 1.vue2通过$parent实现组件传值——父传子 2.vue2 通过$children实现组件传值——子传父 3. provide和inject传值&#xff08;依赖注入&#xff09; 4.vue2如何操作dom 5.vue2如何拿到最新的dom 6.filters过滤器 7.vue2的生命周期 8.vuex的用法 1.vue2通过$parent…

LLDP 基本原理

LLDP 简介 定义 LLDP&#xff08;Link Layer Discovery Protocol&#xff0c;链路层发现协议&#xff09;是 IEEE 802.1ab 中定义的第二层发现&#xff08;Layer 2 Discovery&#xff09;协议。 LLDP 提供了一种标准的链路层发现方式&#xff0c;可以将本端设备的主要能力、…

Wp-scan一键扫描wordpress网页(KALI工具系列三十二)

目录 1、KALI LINUX 简介 2、Wp-scan工具简介 3、信息收集 3.1 目标IP&#xff08;服务器) 3.2kali的IP 4、操作实例 4.1 基本扫描 4.2 扫描已知漏洞 4.3 扫描目标主题 4.4 列出用户 4.5 输出扫描文件 4.6 输出详细结果 5、总结 1、KALI LINUX 简介 Kali Linux 是一…

决策树划分属性依据

划分依据 基尼系数基尼系数的应用信息熵信息增益信息增益的使用信息增益准则的局限性 最近在学习项目的时候经常用到随机森林&#xff0c;所以对决策树进行探索学习。 基尼系数 基尼系数用来判断不确定性或不纯度&#xff0c;数值范围在0~0.5之间&#xff0c;数值越低&#x…

shark云原生-日志管理体系-filebeat

文章目录 1. deploy 文件1.1 RBAC1.2. DaemonSet1.2.1. Elasticsearch 连接信息1.2.2. Volume 1.3. ConfigMap1.3.1. 日志收集路径1.3.2. 日志事件输出目标 2. 在控制平面节点上运行Filebeat3. 查看输出3.1. 关于处理器 processors 4. 日志收集配置4.1. 手动指定日志收集路径4.…

简单多状态DP问题

这里写目录标题 什么是多状态DP解决多状态DP问题应该怎么做&#xff1f;关于多状态DP问题的几道题1.按摩师2.打家劫舍Ⅱ3.删除并获得点数4.粉刷房子5.买卖股票的最佳时期含手冷冻期 总结 什么是多状态DP 多状态动态规划&#xff08;Multi-State Dynamic Programming, Multi-St…

数据结构-顺序表的插入排序

顺序表的排序可以看作数组排序的拓展。基本逻辑和数组排序的逻辑大同小异。 由于顺序表中可以存放不同种的数据类型&#xff0c;进而和结构体排序又有相似之处。其中要注意的是&#xff08;->&#xff09;和&#xff08;.&#xff09;的区别。 -> 符号是针对指针进行的操…

实现了Map接口的HashMap

HashMap 底层主要由以下几个部分组成&#xff1a; 数组 (Node<K,V>[] table): 这是一个数组&#xff0c;存储的是链表的头节点。默认大小为 16。链表 (Linked List): 当发生哈希冲突时&#xff0c;即不同的键具有相同的哈希值&#xff0c;HashMap 使用链表来解决冲突。链…

计网之IP

IP IP基本认识 不使用NAT时&#xff0c;源IP地址和目的IP地址不变&#xff0c;只要源MAC和目的MAC地址在变化 IP地址 D类是组播地址&#xff0c;E类是保留地址 无分类地址CIDR 解决直接分类的B类65536太多&#xff0c;C类256太少a.b.c.d/x的前x位属于网路号&#xff0c;剩…