🐳设计模式之单例模式
引言
设计模式是软件开发中重要的概念之一。单例模式是设计模式中的一种,它用于确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在本文中,我们将深入探讨单例模式的概念和思想,并介绍几种常见的代码实现方式。
单例模式的概念和思想
💧单例模式是一种创建型
设计模式,其主要目的是限制一个类只能有一个实例,并提供一种访问该实例的方式
。这对于需要共享资源
或控制特定资源访问
的场景非常有用。
💧单例模式的核心思想
是通过封装构造函数,使得该类无法通过常规的方式创建实例
。同时,单例模式还提供一个静态方法
或者全局变量
来获取该类的唯一实例
。
常见的代码实现方式 ↓
饿汉式
💧饿汉式是最简单的单例模式实现方式之一。在该实现中,实例在类加载时就被创建,因此称为"饿汉式"。
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { // 私有构造函数 } public static Singleton getInstance() { return instance; } }
在上述代码中,我们通过私有的构造函数确保该类无法在外部被实例化。同时,通过静态变量 instance
保存唯一实例,并通过静态方法 getInstance()
返回该实例。
懒汉式
💧懒汉式是另一种常见的单例模式实现方式。与饿汉式不同,懒汉式在需要时才创建实例。
public class Singleton { private static Singleton instance; private Singleton() { // 私有构造函数 } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
在上述代码中,我们将实例的创建延迟到第一次调用 getInstance()
方法时。这种方式在多线程环境下可能会出现问题,因为多个线程可能同时调用 getInstance()
方法,导致创建多个实例。下面我们将介绍一种改进的懒汉式实现方式。
双重检查
💧双重检查是一种改进的懒汉式实现方式,通过添加同步块来确保只有一个线程能够创建实例。
public class Singleton { private static volatile Singleton instance = null; ```java private Singleton() { // 私有构造函数 } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
在上述代码中,我们首先检查实例是否已经存在,如果不存在,则进入同步块。在同步块内部,再次检查实例是否为空,如果为空,则创建实例。通过使用 volatile
关键字修饰 instance
变量,确保在多线程环境下对变量的可见性,避免出现创建多个实例的情况。
静态内部类
💧静态内部类是一种常见的延迟初始化的单例模式实现方式。在该实现中,使用内部类来持有实例,并在需要时进行初始化。
public class Singleton { private Singleton() { // 私有构造函数 } private static class SingletonHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
在上述代码中,我们将实例的创建放在了静态内部类 SingletonHolder
中。当调用 getInstance()
方法时,会返回 SingletonHolder
中的实例,从而实现了延迟初始化的效果。这种方式利用了类加载的机制来保证线程安全,同时又避免了同步块带来的性能开销。
枚举
💧枚举是一种简洁且安全的单例模式实现方式。在枚举中,每个枚举常量都是该枚举类型的一个实例。
public enum Singleton { INSTANCE; // 添加其他成员和方法 }
在上述代码中,我们使用了一个单独的枚举常量 INSTANCE
来表示该单例的实例。通过直接访问枚举常量 INSTANCE
,可以获取到该实例。枚举的特性保证了该实例是全局唯一的,同时也提供了线程安全的保证。
总结
通过使用单例模式,我们可以确保一个类只有一个实例,并提供全局访问点来获取该实例。这在需要共享资源或控制资源访问的场景下非常有用。我们在使用单例模式时也需要注意线程安全和性能等方面的考虑。