头一次见单例模式讲的如此透彻

news2024/11/25 1:01:15

简介

单例模式是一种常用的软件设计模式,用于创建类型。通过单例模式的方法创建的类在当前进程中只有一个实例。单例模式的类只能允许一个实例存在。单例模式的作用是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个。

组成部分:

  1. 私有化构造方法。

  2. 私有化内部实例。

  3. 公有静态方法用来获取内部实例。

单例模式

优缺点

单例模式的优点有:

  • 提供了对唯一实例的受控访问,可以保证对象的唯一性和一致性。

  • 减少了内存开销,避免了频繁的创建和销毁对象。

  • 避免了对资源的多重占用,例如文件操作、数据库连接等。

单例模式的缺点有:

  • 不支持继承和多态,违反了单一职责原则,一个类应该只关心内部逻辑,而不关心外部如何实例化。

  • 不易扩展,如果需要创建多个实例,就需要修改代码,违反了开闭原则,一个类应该对扩展开放,对修改关闭。

  • 不支持有参数的构造函数,如果需要传递参数,就需要修改方法或者定义其他方法。

  • 可能存在反射或者反序列化攻击,破坏单例的唯一性。

应用场景

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

  • 需要频繁创建和销毁的对象,例如缓存、线程池、注册表等。

  • 需要控制资源的访问,例如文件操作、数据库连接等。

  • 需要保证对象的唯一性和一致性,例如配置信息、全局变量等。

Java 代码示例

在 Java 中,有五种不同的单例实现方法。其中包括饿汉式、懒汉式、双检锁、静态内部类和枚举类。 单例模式的五种实现原理分别是饿汉式、懒汉式、双重检测、静态内部类和枚举类。它们各自的优缺点如下:

  • 饿汉式:原理是在类加载的时候,就创建并初始化一个静态的实例对象,然后通过一个静态的方法返回这个实例。优点是线程安全,不需要加锁;缺点是不支持延迟加载,可能会浪费资源。

public class Singleton {
    private Singleton() {}
    private static Singleton instance;
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • 懒汉式:原理是在第一次调用获取实例的方法时,才创建并初始化一个静态的实例对象,然后返回这个实例。为了保证线程安全,需要给获取实例的方法加上synchronized关键字。优点是支持延迟加载,节省资源;缺点是线程不安全,需要加锁,影响性能。

public class Singleton {
    private Singleton() {}
    private static final Singleton instance = new Singleton();
    public static Singleton getInstance() {
        return instance;
    }
}
  • 双重检测:原理是在第一次调用获取实例的方法时,先判断静态的实例对象是否为空,如果为空,则进入同步代码块,再判断一次是否为空,如果为空,则创建并初始化一个静态的实例对象,然后返回这个实例。为了防止指令重排序导致空指针异常,需要给静态的实例对象加上volatile关键字。优点是线程安全,支持延迟加载,不需要加锁;缺点是可能会出现空指针异常,需要使用 volatile 关键字防止指令重排序。

public class Singleton {
    private Singleton() {}
    private static volatile Singleton instance;
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 静态内部类:原理是利用了 Java 静态内部类的特性,即外部类加载时不会加载内部类,只有在使用到内部类时才会加载。因此,在第一次调用获取实例的方法时,才会加载静态内部类,并创建并初始化一个静态的实例对象,然后返回这个实例。优点是线程安全,支持延迟加载,不需要加锁;缺点是不能防止反射或者反序列化攻击。

public class Singleton {
    private Singleton() {}
    private static class Instance {
        private static final Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
        return Instance.instance;
    }
}
  • 枚举类:原理是利用了Java枚举类型本身的特性,即枚举类型在加载时就会创建所有的枚举常量,并且保证了线程安全性和唯一性。因此,在调用获取实例的方法时,直接返回枚举常量即可。优点是线程安全,简单易用,可以防止反射或者反序列化攻击;缺点是不支持延迟加载,不能继承其他类。

public enum Singleton {
     INSTANCE;
}

这些不同的实现方式有不同的适用场景,需要根据具体的需求和条件来选择。在这里,我只能给出一些个人的看法,仅供参考。

  • 如果对内存资源比较敏感,或者单例对象不需要频繁使用,可以考虑使用懒汉式或者双重检测,因为它们支持延迟加载,可以节省资源。

  • 如果对性能比较敏感,或者单例对象需要频繁使用,可以考虑使用饿汉式或者静态内部类,因为它们不需要加锁,可以提高效率。

  • 如果对安全性比较敏感,或者需要防止反射或者反序列化攻击,可以考虑使用枚举类,因为它可以保证实例的唯一性和不可变性。

  • 如果对简洁性比较敏感,或者不需要继承其他类,可以考虑使用枚举类,因为它是最简单的实现方式。

个人来说在编码效率和可维护性上我比较倾向于使用静态内部类的实现方式,既能保证线程安全性,又能支持延迟加载。

Spring 代码示例

在 Spring 框架中,Spring 默认使用单例模式来创建和管理 Bean 对象,但是可以通过 @Scope("singleton") 注解来指定 Bean 对象的作用域。

  • @Scope("singleton"):表示该Bean对象是一个单例对象,在整个Spring容器中只有一个实例。

  • @Scope("prototype"):表示该Bean对象是一个原型对象,在每次请求时都会创建一个新的实例。

  • @Scope("request"):表示该Bean对象的作用域是一个HTTP请求,在同一个请求中只有一个实例。

  • @Scope("session"):表示该Bean对象的作用域是一个HTTP会话,在同一个会话中只有一个实例。

总结

单例模式是一种简单而常用的设计模式,它可以保证一个类只有一个实例,并提供一个全局访问点。单例模式有多种实现方式,各有优缺点。单例模式可以节约系统资源,避免资源冲突,保证对象的唯一性和一致性。但是单例模式也有不利于继承和扩展的缺点,以及可能存在的安全隐患。在使用单例模式时,需要根据具体情况和需求选择合适的方法,并注意避免潜在的问题。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!

 

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

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

相关文章

【springboot整合】Spring缓存抽象

JSR-107简介 为了统一缓存开发规范,以及提升缓存开发的扩展性,J2EE发布了JSR-107缓存开发规范。 Java Caching定义了5个核心接口,分别是CachingProvider、CacheManger、Cache、Entry和Expiry CachingProvider:定义了创建、配置…

基于Java毕业论文管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍: ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精…

Redis【入门篇】---- Redis常见命令

Redis【入门篇】---- Redis常见命令 1. Redis数据结构介绍2. Redis 通用命令3. Redis命令-String命令4. Redis命令-Key的层级结构5. Redis命令-Hash命令6. Redis命令-List命令7. Redis命令-Set命令8. Redis命令-SortedSet类型 1. Redis数据结构介绍 Redis是一个key-value的数据…

调查问卷Type Form的集成

简介 Typeform是一家制作线上调查问卷的公司。 Muoz 和 David Okuniev两人于2012年创作出一个更加动态、更具交互性的用户调查工具,每次只提一个问题,并且根据用户的回答为其呈现下一个问题,像和朋友间的对话一样,让用户在不知不…

边缘计算开源平台

边缘计算 文章目录 边缘计算前言01 边缘计算开源平台概述02 面向物联网端的边缘计算开源平台2.1 EdgeXFoundry2.2 ApacheEdgent 03 面向边缘云的边缘计算开源平台3.1 CORD3.2 Akraino EdgeStack 04 面向云边融合的边缘计算开源平台05 构建边缘计算平台的开源软件06 结束语 前言…

类皮肤全属性凝胶电子皮肤

目前电子皮肤相关工作仅①提升单一或几个刺激感知属性(压力、温度等);②研究部分理化属性和感知属性的结合。但这些工作仅覆盖皮肤的两种或三种属性,距离实现皮肤般丰富的刺激感知感官和理化特性还有很大差距。而覆盖人类皮肤的所…

linux-virtualbox安装centOS7.9

一、windows10安装virtualbox 安装包->右键->以管理员身份运行->下一步 ->选择安装位置->下一步 ->是(网络中断?) ->是(安装一些辅助工具包) ->安装 ->完成 二、virtualbox新建centOS7.9虚…

【Python 基础篇】Python 文件操作

文章目录 导言一、文件操作的作用二、文件的基本操作1、打开文件2、读写文件① 读取文件② 写入文件 3、关闭文件 三、文件备份四、文件和文件夹的操作结语 导言 在编程领域中,文件操作是一项基础且常见的任务。无论是读取配置文件、处理数据文件,还是备…

MySQL保姆安装教程

文章目录 前言一、MySQL官网二、离线安装包步骤三、环境配置四、验证安装是否成功在这里插入图片描述 五、可视化工具连接总结 前言 对于第一次安装mysql是有点难度,现在我会把安装流程搞出来。 一、MySQL官网 MySQL Installer 8.0.33安装(不想安装这个…

Windows下redis的安装与使用

一、下载 redis.io 官网没有Windows版本的,需要去redis-windows下载。 二、使用与配置 2.1 解压安装 redis的Windows版本,有.msi和.zip两种格式。这里使用更为方便,直接解压就可以使用的.zip格式。 将Redis-x64-5.0.14.1.zip解压至D盘的…

【Java-SpringBoot+Vue+MySql】Day3.3-MybatisPlus说明与使用

目录 一、MybatisPlus快速入门 1、知识轰炸 2、实操演练 (1)新建项目 (2)添加依赖 (3)添加配置 (4)添加映射层 (5)启动类中添加注解 (6&a…

【通过Data Studio连接openGauss】---快速入门

【通过Data Studio连接openGauss】---快速入门 🔻 一、访问openGauss🔰 1.1 确认连接信息(单节点)🔰 1.2 使用gsql访问openGauss(本地连接数据库)🔰 1.3 使用gsql访问openGauss&…

玩机搞机------安卓手机分区操作中的的各种工具 提取分区 备份分区 檫除分区 推荐一

喜欢玩机搞机的朋友们经常对手机系统进行安装玩机操作。但有时候指令类输入和操作步骤比较繁琐。耽误时间。有些工具就比较方便操作。陆续会整理一些玩机搞机中的简单工具给爱好者使用。本期整理一些关于手机分区的工具推荐 💔💔💔 AB AVB分…

Android的详细介绍

目录: Android诞生 Android系统架构 Android系统版本 Android应用开发特色 Android诞生 2003年10月,Andy Rubin等人创建了Android公司,并组建了Android团队。 2005年8月17日,Google低调收购了成立仅22个月的高科技企…

【新星计划·2023】Linux目录结构

作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 前言 本文将讲解Linux目录结构与功能,以及目录解释,最近这段时间会持续更新关于Linux的基础知识,期待你的…

机器视觉初步6-1:基于梯度的图像分割

把基于梯度的图像分割单独拿出来。 文章目录 一、图像梯度相关算子的原理1. Sobel算子2. Prewitt算子3. Roberts算子 二、python和halcon算子实现1.python实现2.halcon实现 基于梯度的图像分割方法利用像素之间的梯度信息来进行图像分割。 梯度 1是图像中像素灰度值变化最快的…

macOS Monterey 12.6.7 (21G651) 正式版发布,ISO、IPSW、PKG 下载

macOS Monterey 12.6.7 (21G651) 正式版发布,ISO、IPSW、PKG 下载 本站下载的 macOS 软件包,既可以拖拽到 Applications(应用程序)下直接安装,也可以制作启动 U 盘安装,或者在虚拟机中启动安装。另外也支持…

macOS Big Sur 11.7.8 (20G1351) 正式版 ISO、PKG、DMG、IPSW 下载

macOS Big Sur 11.7.8 (20G1351) 正式版 ISO、PKG、DMG、IPSW 下载 本站下载的 macOS 软件包,既可以拖拽到 Applications(应用程序)下直接安装,也可以制作启动 U 盘安装,或者在虚拟机中启动安装。另外也支持在 Window…

Windows 10 |VMware开启虚拟化的最全面说明

前言: Windows作为工作机,对于计算机系的同学来说,主要是在于利用图形化的界面直观的创建虚拟机(典型的有代表性的是virtualbox和VMware这两家公司的桌面级虚拟化软件),尤其是小白这样的初学者&#xff0c…

吴恩达ChatGPT《Prompt Engineering》笔记

ChatGPT 提示词工程师教程 1. 课程介绍 1.1 ChatGPT 相关术语 LLM:Large Language Model,大语言模型 Instruction Tuned LLM:经过指令微调的大语言模型 Prompt:提示词 RLHF:Reinforcement Learning from Human F…