什么是单例模式?单例模式的作用?单例模式的使用场景等...

news/2024/11/7 15:11:50/

设计模式(一)单例模式详解

一、单例模式

什么是单例模式

单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。在Java中,单例模式通过以下几种方式实现:

  1. 将构造方法私有化,防止外部直接创建实例。

  2. 定义一个静态变量来保存唯一的实例。

  3. 提供一个公共的静态方法来返回这个实例。

单例模式的作用?
  1. 资源节约:确保系统中某个类只有一个实例,减少不必要的内存开销。

  2. 全局访问:提供一个全局访问点,方便在整个应用中访问同一个实例。

  3. 控制共享资源访问:确保对共享资源的访问是安全的且一致的。

为什么使用单例模式
  • 简化配置管理:对于需要频繁实例化然后销毁的对象,使用单例模式可以简化配置管理。

  • 降低耦合度:通过单例模式,系统中的所有对象都可以通过一个统一的方式访问某个实例,从而降低类之间的耦合度。

  • 避免多线程问题:多线程环境中,单例模式可以保证对象的唯一性,避免多线程同时操作同一个对象带来的问题。

单例模式的使用场景
  1. 日志文件管理:系统中通常只需要一个日志文件管理器来记录日志信息。

  2. 数据库连接池:为了提高性能,数据库连接池通常设计成单例模式,避免每次连接数据库时都要重新创建连接。

  3. 任务调度器:在一个系统中往往只需要一个任务调度器来管理任务的执行。

  4. 配置管理:应用程序的配置信息通常只需要加载一次,因为此配置管理类适合采用单例模式实现。

单例模式的分类
1、懒汉式1(线程不安全的)多线程环境下会出错。

懒加载:只有在第一次调用getInstance()方法时才会创建实例

java">package com.briup.singletonMyself;/*** 懒汉式单例1(线程不安全的)* @author 35329*/
public class LazySingleton1 {// 声明一个保存本类实例引用的静态变量private static LazySingleton1 instance;// 将构造方法私有化、防止其他类创建该类对象private LazySingleton1(){}// 提供一可以获取唯一实例的静态方法public static LazySingleton1 getInstance(){if (instance == null){instance = new LazySingleton1();}return instance;}
}
2、懒汉式2(线程安全)使用synchronized关键字保证线程安全,但每次调用getInstance()方法都会加锁,性能较低。
java">package com.briup.singletonMyself;/*** @author 35329** 懒汉式单例2(线程安全的)*/
public class LazySingleton2 {// instance: 实例private static LazySingleton2 instance;// 私有的构造器private LazySingleton2(){}// 专门创建一个静态性质的对象,充当同步锁private final static Object lock = new Object();// 提供一个方法,用于获取该实例public static LazySingleton2 getInstance(){synchronized (lock){if (instance == null){instance = new LazySingleton2();}}return instance;}
}
3、懒汉式3(使用synchronized和volatile修饰符确保多线程环境下的安全性,同时避免了每次调用getInstance()方法时都进行同步的性能开销)
java">package com.briup.singletonMyself;/*** @author 35329* 懒汉式单例3:* 1、对对象的创建和判断是否为空的操作 以原子性执行* 2、将类中的实例instance使用volatile修饰符修饰*/
public class LazySingleton3 {// instance : 静态变量,用来保存单例对象的唯一实例。// volatile修饰符:确保多线程环境下instance的可见性和有序性,// 防止指令重排导致的问题private volatile static LazySingleton3 instance;// 将构造方法私有化private LazySingleton3(){}// 使用静态对象作为同步锁,确保线程安全private final static Object lock = new Object();// 专门提供一个方法,用于获取该实例public static LazySingleton3 getInstance(){// synchronized(lock)确保在多线程环境下getInstance()方法内的代码块是同步执行的。synchronized (lock){// 只有确保在instance为null时才会创建新的实例if (instance == null){instance = new LazySingleton3();}}return instance;}
}
4、懒汉式+线程同步+可见性+DCL(双重锁验证机制)
java">package com.briup.singletonMyself;/*** @author 35329* 单例模式:懒汉式+线程同步+可见性+DCL* DCL:Double Check Lock,双重锁验证机制*/
public class DCLSingleton {// instance 实例private volatile static DCLSingleton instance;// 私有构造器private DCLSingleton(){}// 同步锁 确保线程安全private static final Object lock = new Object();// 提供一个方法,用于获取该实例public static DCLSingleton getInstance(){if (instance == null){// synchronized (DCLSingleton.class) 这两句相同 详细解析看下方注释synchronized (lock){if (instance == null){instance = new DCLSingleton();}}}return instance;}/** synchronized (DCLSingleton.class) 是DCLSingleton类的对象引用* 类对象锁是针对类对象的锁,可以确保在类加载时只有一个线程能够进入同步块* * synchronized(lock) 是一个普通的对象引用,对象锁是针对特定对象的锁,* 可以确保在多线程的环境下只有一个线程能够进入同步块。* 由于lock是静态对象,因此所有对DCLSingleton类的实例化操作都会受到这个锁的影响。* 这种方式可以确保在多线程环境下,只有一个线程能够进入同步块并创建实例。* * 这两种方式都能保证线程安全,但synchronized(lock)更常用,因为它不会影响* 类的其他操作。而synchronized(XXXXX.class)虽然也能保证线程安全,但可能会影响类的其他操作。* 具体选择那种方式取决于实际需求和性能考虑。*/
}
5、饿汉式
java">package com.briup.singletonMyself;/*** 饿汉式单例:不使用显示初始化,而是使用static{}对实例进行创建*/
public class HungrySingleton {// 创建一个Hungry类的唯一实例private final static HungrySingleton INSTANCE;static {INSTANCE = new HungrySingleton();}// 私有构造函数,防止外部实例化private HungrySingleton(){}// 提供一个公共的静态方法,用于返回唯一的实例public static HungrySingleton getInstance(){return INSTANCE;}
}
6、静态内部类
java">package com.briup.singletonMyself;/*** @author 35329* 单例模式:借助静态内部类实现*/
public class StaticInnerSingleton {// 将构造器私有化,防止外界创建该类对象private StaticInnerSingleton(){}/*** InstanceHolder是一个静态内部类,它持有StaticInnerSingleton的唯一实例** INSTANCE:是一个静态最终变量,用于保存StaticInnerSingleton的唯一实例** 静态内部类InstanceHolder只会在首次访问getInstance()方法时被加载,* 此时INSTANCE会被初始化。由于类加载是线程安全的,因此这种方法保证了线程的安全*/private static class InstanceHolder{ // 外部类实例的持有者// 将外部类的唯一实例声明在这里private static final StaticInnerSingleton INSTANCE = new StaticInnerSingleton();}// 提供了一个静态方法用于获取唯一的实例// 懒加载:只有在首次调用getInstance()方法时才会创建实例,之后每次调用都会返回已创建的实例public static StaticInnerSingleton getInstance(){return InstanceHolder.INSTANCE;}}
7、枚举
java">package com.briup.singletonMyself;/*** @author 35329* * 单例模式:枚举实现* 过早的将对象创建出来加载到内存,但是线程是安全的,简洁,推荐使用*/
public enum EnumSingleton {INSTANCE;  // 唯一的实例// 定义一个静态方法 用来返回该实例的方法public static EnumSingleton getInstance(){return INSTANCE;}
}

后续设计模式等待更新中...


http://www.ppmy.cn/news/1539476.html

相关文章

2022年黄河流域旅游资源空间分布数据(shp)

数据介绍 黄河是中华民族的母亲河。黄河流域旅游资源丰富且极具特色。黄河流域旅游资源空间分布数据是黄河流域旅游资源开发与决策的基础。本数据集以县(区)域行政边界为单元、以国家旅游资源分类标准为依据,收集整理了黄河流域各县&#xf…

【TFT彩屏移植】STM32F4移植1.8寸TFT彩屏简明教程

目录 一.移植说明 二.移植 1.例程 物理接口: 延时函数: 底层驱动文件: GUI界面文件: 测试demo: 2.移植至F4 创建工程: 调试接口选择SW: RCC中HSE选择外部晶振: GPIO配置不变&am…

Golang | Leetcode Golang题解之第468题验证IP地址

题目: 题解: func validIPAddress(queryIP string) string {if sp : strings.Split(queryIP, "."); len(sp) 4 {for _, s : range sp {if len(s) > 1 && s[0] 0 {return "Neither"}if v, err : strconv.Atoi(s); err …

C Programming Basics

1.C语言的基本介绍 Basics of the C Programming Language • C 是一种编程语言,它的发明是为了进行低级别的系统编程工作。C 语言从 B 语言发展而来,是一种非常紧凑(compact)的语言。 • 它是一种通用(general)编程语言,既可以用于系统编程…

Lua 协同程序(coroutine)

Lua 协同程序(coroutine) 概述 Lua 语言以其轻量级和易于嵌入的特点,在游戏开发、脚本编写等领域广受欢迎。Lua 中的协同程序(coroutine)是其并发编程的核心特性之一。协同程序提供了一种不同于多线程的并发执行方式,它允许多个代码段交替执行,而不是同时执行。这种机制…

安卓上的iso 是哪几个gain 相乘

在安卓的相机系统中,ISO 表示感光度,它实际上反映的是图像传感器对光线的整体响应度。ISO 值的调整可以通过增益(gain)的调节实现,增益会放大传感器采集的信号强度。通常,ISO 是通过以下几种增益相乘得到的…

歌曲怎么去掉原唱只留伴奏?创作无界,轻松获取伴奏音轨

在音乐制作、翻唱或是卡拉OK等场合,我们经常需要歌曲的伴奏版本,即去掉原唱声音,只保留背景音乐的部分。然而,并非每首歌曲都会官方发布伴奏版本,这时我们就需要借助一些技术手段来实现这一目标。本文将介绍几种常见的…

PythonAI 学习大纲

设计一套学习Python在AI方向的入门教程需要涵盖基础知识、编程技能、AI原理、以及具体的AI技术和应用。以下是一个分阶段、模块化的教程大纲,旨在帮助初学者逐步掌握Python在AI领域的应用。 第一阶段:Python基础与编程技能 第1周:Python入门…