设计模式之单例模式

单例模式

在 Java 中,单例模式是一种设计模式,用于确保某个类只有一个实例,并提供一个全局访问点来获取该实例。单例模式通常用于需要全局访问点的场景,例如日志记录器、数据库连接池、配置文件管理等。

实现单例模式的关键点是:

  1. 将类的构造函数私有化,防止外部直接实例化该类
  2. 提供一个静态方法来获取类的唯一实例,通常命名为 getInstance()getInstance(int param) 等。

在单例模式中,“懒汉”、"饿汉"和"枚举"是三种常见的实现方式,它们分别指代不同的单例对象创建策略。

  1. 懒汉模式(Lazy Initialization)

    • 懒汉模式是指在首次使用时才创建对象实例的方式。在多线程环境下,需要考虑线程安全性,通常会使用双重检查锁定(Double-Checked Locking)等机制来确保线程安全。

      public class LazySingleton {
          private static LazySingleton instance;
          
          private LazySingleton() {
              // 私有构造方法,避免外部直接实例化
          }
          
          public static LazySingleton getInstance() {
              if (instance == null) {
                  instance = new LazySingleton();
              }
              return instance;
          }
      }
      

      在上面的代码中,LazySingleton 类采用懒汉模式实现单例模式。在 getInstance 方法中,当第一次调用时会创建单例实例,之后再次调用时直接返回已创建的实例。

      需要注意的是,懒汉模式在多线程环境下可能存在线程安全性问题,可能会导致创建多个实例。为了解决这个问题,可以在 getInstance 方法上加锁,或者使用双重检查锁定等方式来确保线程安全。

      以下是使用双重检查锁定方式实现线程安全的懒汉模式的示例代码:

      public class ThreadSafeLazySingleton {
          private volatile static ThreadSafeLazySingleton instance;
      
          private ThreadSafeLazySingleton() {
              // 私有构造函数,防止外部直接实例化
          }
      
          public static ThreadSafeLazySingleton getInstance() {
              if (instance == null) {
                  synchronized (ThreadSafeLazySingleton.class) {
                      if (instance == null) {
                          instance = new ThreadSafeLazySingleton();
                      }
                  }
              }
              return instance;
          }
      }
      
  2. 饿汉模式(Eager Initialization)

    • 饿汉模式是指在类加载时就创建对象实例的方式,无论后续是否会被使用到。这种方式简单直接,但可能会导致资源浪费。在多线程环境下,需要注意线程安全问题。

      public class EagerSingleton {
          private static final EagerSingleton instance = new EagerSingleton();
          
          private EagerSingleton() {
              // 私有构造方法,避免外部直接实例化
          }
          
          public static EagerSingleton getInstance() {
              return instance;
          }
      }
      

      在上面的代码中,EagerSingleton 类采用饿汉模式实现单例模式。在类加载时,静态变量 instance 就被创建并初始化为单例实例,随后通过静态方法 getInstance 返回已创建的实例。

      饿汉模式保证了在多线程环境下也能保持单例的唯一性,因为在类加载时就创建了单例实例。但需要注意的是,由于单例实例在类加载时就被创建,可能会导致资源的浪费,特别是在单例实例较大或者初始化耗时较长的情况下。

      总的来说,饿汉模式适用于单例实例较小且初始化较快的情况,可以确保线程安全性。

  3. 枚举模式(Enum Singleton)

    • 枚举单例模式利用 Java 中的枚举类型来实现单例。枚举类型在 Java 中保证只有一个实例,并且在任何情况下都是单例。这种方式简洁高效,并且天然地提供了线程安全性和防止反序列化重新创建对象的保障。

      public class EnumExample {
          // 定义一个枚举类型表示星期几
          public enum Day {
              MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
          }
      
          public static void main(String[] args) {
              // 使用枚举类型来表示今天是星期几
              Day today = Day.MONDAY;
      
              // 使用枚举类型的常量
              switch (today) {
                  case MONDAY:
                      System.out.println("Today is Monday");
                      break;
                  case TUESDAY:
                      System.out.println("Today is Tuesday");
                      break;
                  // 其他星期的处理
                  default:
                      System.out.println("Today is " + today);
              }
          }
      }
      

​ 在上面的代码中,我们定义了一个枚举类型 Day 表示星期几,包含了每一天作为枚举常量。在 main 方法中,我们使用枚举类型 Day 来表示今天是星期几,并根据不同的情况输出相应的信息。

枚举模式在实际开发中常用于表示一组相关的常量,例如表示状态、类型等。它提供了一种类型安全的方式来操作这些常量,并且可以让代码更加清晰易懂。

总的来说,懒汉模式是延迟加载的方式,在需要时才创建实例;饿汉模式是在类加载时就创建对象实例;而枚举模式利用枚举类型的特性来实现单例,是一种简洁高效的实现方式。

上一篇:#设计模式#4.6 Flyweight(享元) 对象结构型模式


下一篇:大语言模型(LLM)token解读