单例模式 (Singleton Pattern)

定义:

单例模式(Singleton Pattern)是一种常用的软件设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。单例模式主要用于控制对某个资源或服务的访问,确保整个系统中只有一个对象实例负责这些操作。

单例模式的关键特点包括:

  1. 单一实例
    • 该模式确保一个类只有一个实例存在。通常通过隐藏该类的构造函数,并提供一个静态方法来创建和获取这个唯一实例。
  2. 全局访问点
    • 单例类提供了一个全局访问点,通过这个访问点可以访问唯一实例。这通常是一个静态方法,例如 getInstance()
  3. 自我实例化
    • 单例类负责创建自己的唯一实例,并确保没有其他实例被创建。
  4. 延迟初始化(可选):
    • 在单例模式中,实例通常在首次使用时创建,这称为延迟初始化。这有助于减少资源的浪费和提高性能。
解决的问题:
  • 控制实例创建
    • 确保一个类只有一个实例被创建。这对于控制资源的使用非常重要,尤其是当对象的创建和管理需要消耗大量资源时(如访问共享资源或共享服务)。
  • 全局访问点
    • 提供一个全局访问点以访问该类的唯一实例。这意味着从系统的任何地方都可以访问这个实例,而不需要重新创建或通过特定对象传递。
  • 替代全局变量
    • 单例模式提供了一种更好的方式来创建和管理全局对象,避免了使用全局变量所带来的潜在风险和复杂性。
  • 共享资源或状态管理
    • 当多个对象需要共享同一资源或状态时(例如配置信息、缓存、数据库连接池等),单例模式可以确保所有对象都使用相同的实例,从而实现有效的资源共享和管理。
  • 控制并发访问
    • 在多线程环境中,单例模式可以被用来控制对共享资源的并发访问,确保在任何时刻只有一个实例管理着资源,减少资源冲突的可能性。
使用场景:
  • 资源共享
    • 当系统中的不同组件需要共享相同的资源或服务时,如数据库连接池、日志记录、配置管理等。单例模式确保这些组件都访问同一个实例,从而实现资源的有效共享。
  • 全局状态或配置
    • 当需要在应用程序的不同部分之间共享全局状态或配置信息时。例如,应用程序的配置设置通常在多个地方被使用,单例模式可以提供一个统一的接口来访问这些设置。
  • 控制资源访问
    • 对于需要严格控制客户端如何以及何时访问某个资源的场景。单例模式可以确保对资源的访问在整个应用程序中是同步的,从而避免资源冲突和数据不一致。
  • 日志记录
    • 日志记录通常在整个应用程序中是统一的操作。使用单例模式可以确保全局只有一个日志记录器在运行,从而保持日志记录的一致性。
  • 硬件接口访问
    • 当访问硬件资源时(如打印机或文件系统),通常需要确保全局只有一个实例负责与硬件的交互,避免可能的资源冲突。
  • 性能优化
    • 在创建对象特别消耗资源的情况下,单例模式可以减少内存开销和性能开销,因为它避免了重复创建和销毁同一对象。
示例代码:
1. 懒汉式(线程不安全)
public class SingletonLazy {private static SingletonLazy instance;private SingletonLazy() {}public static SingletonLazy getInstance() {if (instance == null) {instance = new SingletonLazy();}return instance;}
}
  • 优点:延迟加载,只有在需要时才创建实例。
  • 缺点:线程不安全,如果多个线程同时访问,可能会创建多个实例。
2. 懒汉式(线程安全)
public class SingletonLazySynchronized {private static SingletonLazySynchronized instance;private SingletonLazySynchronized() {}public static synchronized SingletonLazySynchronized getInstance() {if (instance == null) {instance = new SingletonLazySynchronized();}return instance;}
}
  • 优点:延迟加载,线程安全。
  • 缺点:同步方法降低了效率。
3. 饿汉式(线程安全)
public class SingletonEager {private static final SingletonEager INSTANCE = new SingletonEager();private SingletonEager() {}public static SingletonEager getInstance() {return INSTANCE;}
}
  • 优点:简单,线程安全。
  • 缺点:类加载时就完成实例化,没有达到延迟加载的效果。
4. 双重校验锁(线程安全)
public class SingletonDoubleCheckedLocking {private static volatile SingletonDoubleCheckedLocking instance;private SingletonDoubleCheckedLocking() {}public static SingletonDoubleCheckedLocking getInstance() {if (instance == null) {synchronized (SingletonDoubleCheckedLocking.class) {if (instance == null) {instance = new SingletonDoubleCheckedLocking();}}}return instance;}
}
  • 优点:既保证了延迟加载,又保证了线程安全,效率较高。
  • 缺点:实现复杂。
5. 静态内部类(线程安全)
public class SingletonStaticInnerClass {private static class SingletonHolder {private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();}private SingletonStaticInnerClass() {}public static SingletonStaticInnerClass getInstance() {return SingletonHolder.INSTANCE;}
}
  • 优点:实现简单,延迟加载,线程安全。
  • 缺点:实现方式可能不够直观。
6. 枚举方式(线程安全)
public enum SingletonEnum {INSTANCE;public void doSomething() {// 执行操作}
}
  • 优点:简单,提供了序列化机制,绝对防止多次实例化。
  • 缺点:不是懒加载模式(非延迟加载)。

每种方法都有其适用场景,根据实际需求选择最合适的实现方式。

主要符合的设计原则:
  1. 单一职责原则(Single Responsibility Principle)
    • 单例模式确保了类有一个单一的职责,即管理自己的唯一实例。这个类负责创建、管理这个实例,并提供一个全局访问点。
  2. 开闭原则(Open-Closed Principle)
    • 单例模式在某种程度上符合开闭原则。一旦单例类被正确实现,它就可以在不修改源代码的情况下保持开放性(例如,可以继承自单例类)。但是,由于单例类控制了实例化过程,扩展其功能可能需要修改源代码,这在某种程度上限制了其对开闭原则的遵循。
  3. 里氏替换原则(Liskov Substitution Principle)
    • 单例模式不完全符合里氏替换原则。由于单例类的构造函数是私有的,子类无法直接继承这个构造函数。如果需要继承单例类,就需要在子类中重写实例控制的逻辑。
  4. 接口隔离原则(Interface Segregation Principle)
    • 单例模式并不直接关注接口隔离原则,因为它通常不涉及接口的多重继承。单例类提供的接口是围绕其唯一实例的管理。
  5. 依赖倒转原则(Dependency Inversion Principle)
    • 单例模式可以支持依赖倒转原则。虽然单例对象通常由单例类自身管理,但是单例类可以实现接口,使得高层模块依赖于抽象而不是具体的实例。

综上所述,单例模式主要体现了单一职责原则,但在其他几个设计原则方面的适用性较为有限。它专注于控制类实例的数量,而在继承性和接口设计方面的灵活性不如其他设计模式。

在JDK中的应用:
  • java.lang.Runtime:
    • Runtime 类提供了与Java运行时环境交互的方法。它是一个单例,因为每个Java应用程序有一个且只有一个运行时环境,所以 Runtime.getRuntime() 方法提供了获取这个唯一实例的全局访问点。
  • java.awt.Desktopjava.awt.Toolkit:
    • 在Java AWT库中,Desktop 类和 Toolkit 类被用来提供平台相关的功能,如桌面或工具包服务。这些类通常以单例模式实现,提供一个全局访问点。
  • Java日志API
    • 在Java日志API中,java.util.logging.LogManager 类被用来维护日志服务的全局状态。它通常被实现为单例,因为全局只需要一个日志管理器。
  • Spring框架中的Bean
    • 虽然不是JDK的一部分,但值得一提的是,在Spring框架中,Bean默认是单例的。Spring容器为每个Bean定义创建一个且只有一个实例。

这些例子展示了单例模式在Java标准库中的应用,特别是在需要全局访问点和统一管理资源的情况下。单例模式通过确保类的单个实例全局可用,简化了对共享资源或服务的访问和管理。

在Spring中的应用:
  • Spring Bean的默认作用域
    • 在Spring框架中,默认情况下,所有通过Spring容器创建的Bean都是单例的。这意味着每个由Spring容器管理的Bean类的实例在Spring的整个应用上下文中只有一个。这样做减少了对象的创建成本,同时也减少了内存的消耗。
  • 服务和组件
    • Spring中的服务和组件(如数据源、事务管理器、工厂类等)通常被配置为单例,因为这些对象通常维护着自己的状态(如数据库连接池),在整个应用中共享这个状态更加高效。
  • 全局状态的维护
    • Spring使用单例模式来维护应用级别的全局状态,如配置属性和环境变量。
  • Spring Security的单例Bean
    • 在Spring Security中,像认证管理器(AuthenticationManager)、用户服务(UserDetailsService)等关键组件通常作为单例存在。

单例模式在Spring框架中的应用帮助管理了Bean的生命周期和状态,确保了资源的高效利用和应用组件的统一访问。同时,由于Spring容器管理着Bean的创建和销毁,所以它还减轻了开发者处理单例实例化和线程安全问题的负担。然而,使用单例Bean时,需要注意Bean的状态管理,避免因状态共享导致的潜在问题。


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

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

相关文章

【蓝桥杯 LCA 差分】 砍树

题目分析: 这道题还是比较裸的一道书上差分的题目了 对于每一对标记点(x,y) 他们之间的路径就是 x − > L C A ( x , y ) − > y x->LCA(x,y)->y x−>LCA(x,y)−>y 这条路径上的每一条边都要经过。 那么对于一条边,什么时候砍掉这条…

Linux快捷控制

Linux快捷控制 工具安装 yum -y install lrzsz wget curl net-tools git防火墙 systemctl status firewalld.service systemctl stop firewalld.service systemctl disable firewalld.service宝塔 yum install -y wget && wget -O install.sh https://download.bt.…

C# 新数插入有序数组

题目&#xff1a; 有n(n<100)个整数&#xff0c;已经按照从⼩到⼤顺序排列好&#xff0c;现在另外给⼀个整数x&#xff0c;请将该数插⼊到序列中&#xff0c;并使新的序列仍然有序。输出新的序列。 样例输入&#xff1a;10 20 30 40 50 15 样例输出&#xff1a;1…

vue3中toRaw 与 markRaw

toRaw 返回由 reactive 或 readonly 方法转换成响应式代理的普通对象。 这是一个还原方法&#xff0c;可用于临时读取&#xff0c;访问不会被代理/跟踪&#xff0c;写入时也不会触发界面更新。 markRaw 标记一个对象&#xff0c;使其永远不会转换为代理。返回对象本身 应…

jsonp 的优缺点

JSONP&#xff0c;全名是JSON with Padding&#xff0c;是一种通过<script>标签来获取跨域数据的策略。它本质上不是一个新的技术&#xff0c;只是JavaScript的普通函数调用的一种形式&#xff0c;即利用了网页脚本的同源策略。 优点&#xff1a; 实现简单&#xff1a;…

bash编程 数组和for循环的应用

bash编程 数组和for循环的应用 1、问题背景2、bash 定义数组3、for循环遍历输出数组所有元素4、编写bash脚本输出每个端口是否在监听状态 1、问题背景 linux服务器开机后&#xff0c;需要检查一组端口是否在监听&#xff0c;以便判断这些端口对应的服务是否在运行。可以考虑使…

解释LED显示屏的裸眼3D特效原理

LED电子大屏幕的3D特效技术正在不断发展&#xff0c;而实现这一技术的原理主要包括分光、分色、分时和光栅等四种方法。这些原理都有各自的特点和应用场景&#xff0c;下面将对它们进行详细介绍。 1. 分光方法 分光方法是一种基于偏振光的3D显示技术。通过使用偏振滤镜或偏振片…

leetCode 841. 钥匙和房间 图遍历 深度优先遍历+广度优先遍历 + 图解

841. 钥匙和房间 - 力扣&#xff08;LeetCode&#xff09; 有 n 个房间&#xff0c;房间按从 0 到 n - 1 编号。最初&#xff0c;除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而&#xff0c;你不能在没有获得钥匙的时候进入锁住的房间。当你进入一个房…

0005Java程序设计-ssm基于微信小程序的校园求职系统

文章目录 摘 要目 录系统设计开发环境 编程技术交流、源码分享、模板分享、网课分享 企鹅&#x1f427;裙&#xff1a;776871563 摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据…

spring 自动装配 bean 有哪些方式

Spring提供了以下几种方式来实现自动装配Bean&#xff1a; 根据名称自动装配&#xff08;byName&#xff09;&#xff1a;Spring容器会根据Bean的名称自动将相应的依赖注入到需要的地方。在XML配置中&#xff0c;可以使用autowire"byName"来启用byName自动装配。 <…

MicroPython STM32F4 RTC功能使用介绍

MicroPython STM32F4 RTC功能使用介绍 &#x1f516;STM32和ESP32 RTC功能差不多&#xff0c;相关篇《MicroPython ESP32 RTC功能使用介绍》&#x1f4cc;固件刷可参考前面一篇《STM32刷Micropython固件参考指南》&#x1f33f; 相关篇《Micropython STM32F4入门点灯》&#x1…

RH2288H V3服务器使用ISO安装系统

1.配置和服务器相同网段地址&#xff0c;RH2288H V3服务器bmc管理网口默认IP是192.168.2.100/24&#xff0c;默认用户root&#xff0c;默认Huawei12#$&#xff0c;网线连接BMC口&#xff0c;登录。默认密码可以在开机时按del键进入配置页面修改 2.配置raid&#xff0c;生产环境…

耗时一个星期整理的APP自动化测试工具大全

在本篇文章中&#xff0c;将给大家推荐14款日常工作中经常用到的测试开发工具神器&#xff0c;涵盖了自动化测试、APP性能测试、稳定性测试、抓包工具等。 一、UI自动化测试工具 1. uiautomator2 openatx开源的ui自动化工具&#xff0c;支持Android和iOS。主要面向的编程语言…

js最新随机字符串,进制数随机字符串,更优秀的随机字符串方式,你绝对没用过的随机字符串方式,可控制位数!

js最新随机字符串&#xff0c;进制数随机字符串&#xff0c;更优秀的随机字符串方式&#xff0c;你绝对没用过的随机字符串方式&#xff0c;可控制位数&#xff01; 函数封装和传参 首先我们&#xff0c;要封装这样一个函数&#xff0c;首先要确定&#xff0c;传入哪些参数。…

java springboot中使用 AOP监听方法执行周期

首先 我们在 pom.xml 中 dependencies标签中加入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>然后 我们随便创建一个类 编写代码如下 package com.ex…

一个基于.NET Core开源、跨平台的仓储管理系统

前言 今天给大家推荐一个基于.NET Core开源、跨平台的仓储管理系统&#xff0c;数据库支持MSSQL/MySQL&#xff1a;ZEQP.WMS。 仓储管理系统介绍 仓储管理系统&#xff08;Warehouse Management System&#xff0c;WMS&#xff09;是一种用于管理和控制仓库操作的软件系统&…

离散数学-集合论基础

3.1集合的基本概念 1&#xff09;集合及元素 2&#xff09;集合的表示 3&#xff09;集合的关系 4&#xff09;特殊集合 3.2集合的运算 并、交、差、对称差 3.3集合的划分与覆盖 3.4排斥包含管理 3.1集合的基本概念 1&#xff09;集合及元素 将某种具有同种属性的个体…

Appium自动化测试:sdk版本和手机版本不兼容你就这样做,分分钟解决问题

使用pythonappium执行自动化测试脚本提示报错 环境&#xff1a;python3.7以上&#xff0c;appium1.21.0&#xff1b;设备&#xff1a;华为max8真机 报错信息&#xff1a; android.intent.category.LAUNCHER -f 0x10200000 exited with code 4294967295; Stderr: Security ex…

双馈风机频率二次跌落,永磁风机一次调频火电水电光伏储能直流一次调频,虚拟惯性下垂控制,虚拟同步机VSG控制,二次调频也可继续深入研究

双馈风机(永磁同步风机)虚拟惯性控制下垂控制参与系统一次调频的Matlab/Simulink模型&#xff0c;调频结束后转速回复&#xff0c;造成频率二次跌落SFD。 系统为三机九节点模型&#xff08;可更换为四机两区域&#xff0c;十机39节点&#xff0c;IEEE39节点&#xff0c;IEEE11…

Windows端口映射/转发功能

Netsh interface portproxy 命令 适用于&#xff1a;Windows Server 2022、Windows Server 2019、Windows Server 2016、Azure Stack HCI、版本 21H2 和 20H2 使用 netsh interface portproxy 命令作为 IPv4 和 IPv6 网络与应用程序之间的代理 。 命令介绍 Windows 从 Windo…