当前位置: 首页> 文旅> 酒店 > 【设计模式】单例模式详解及应用实例

【设计模式】单例模式详解及应用实例

时间:2025/7/11 7:30:44来源:https://blog.csdn.net/promise524/article/details/142072073 浏览次数:1次

单例模式(Singleton Pattern)是一种创建型设计模式,保证一个类在整个程序的生命周期中只有一个实例,并提供一个全局访问点。单例模式广泛用于需要全局唯一实例的场景,比如数据库连接池、日志对象、线程池等。

单例模式的特点

  1. 唯一性:确保一个类只有一个实例。
  2. 延迟实例化:通常使用懒加载机制,即在第一次使用时才创建实例。
  3. 全局访问:提供一个全局访问点供外部获取该实例。

单例模式的实现方式

单例模式有多种实现方式,常见的有以下几种:

1. 懒汉式(Lazy Initialization)

懒汉式的单例模式是延迟初始化的,实例在第一次使用时才创建。这种方式的缺点是线程不安全。

public class SingletonLazy {private static SingletonLazy instance;// 私有化构造函数,防止外部实例化private SingletonLazy() {}// 获取单例对象的静态方法public static SingletonLazy getInstance() {if (instance == null) {instance = new SingletonLazy();}return instance;}
}

缺点: 懒汉式在多线程环境下可能会创建多个实例,因为线程可能会同时通过 if (instance == null) 条件。

2. 线程安全的懒汉式(Synchronized Method)

为了在多线程环境下保证实例的唯一性,可以使用 synchronized 关键字使方法同步。

public class SingletonLazyThreadSafe {private static SingletonLazyThreadSafe instance;private SingletonLazyThreadSafe() {}// 同步方法保证线程安全public static synchronized SingletonLazyThreadSafe getInstance() {if (instance == null) {instance = new SingletonLazyThreadSafe();}return instance;}
}

缺点: 虽然线程安全,但由于 synchronized 关键字的使用,每次调用 getInstance 都会产生一定的性能开销。

3. 双重检查锁定(Double-Checked Locking)

双重检查锁定在性能和线程安全之间做了折中。通过在实例初始化前后都进行检查,减少同步的开销。

public class SingletonDCL {// volatile 保证变量的可见性和有序性private static volatile SingletonDCL instance;private SingletonDCL() {}public static SingletonDCL getInstance() {if (instance == null) { // 第一次检查synchronized (SingletonDCL.class) {if (instance == null) { // 第二次检查instance = new SingletonDCL();}}}return instance;}
}

优点: 在多线程环境中高效且线程安全。

4. 静态内部类(Static Inner Class)

利用 Java 的类加载机制实现懒加载,静态内部类方式在类加载时不会立即实例化,而是在调用 getInstance() 时才加载内部类并创建实例。

public class SingletonStaticInnerClass {private SingletonStaticInnerClass() {}// 静态内部类持有 Singleton 的唯一实例private static class SingletonHolder {private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();}public static SingletonStaticInnerClass getInstance() {return SingletonHolder.INSTANCE;}
}

优点: 线程安全,且没有性能开销,推荐使用。

5. 枚举(Enum Singleton)

使用枚举实现单例是一种比较优雅的方式,因为 Java 枚举本身是线程安全的,并且只能有一个实例。

public enum SingletonEnum {INSTANCE;public void someMethod() {// 业务逻辑}
}

优点: 实现简单,枚举保证了线程安全且防止了反序列化破坏单例。

单例模式使用场景

  • 配置类:当一个类只需要一个实例来提供全局配置时,比如读取配置文件的类。
  • 数据库连接池:只需要一个连接池对象来管理数据库连接。
  • 日志类:应用程序中通常需要一个全局的日志管理类。
  • 线程池:应用程序只需要一个线程池来管理线程。

单例模式的使用技巧

  1. 防止反射破坏单例: 通过私有化构造器的方式可以阻止外部类直接使用 new 创建实例,但通过反射可以访问私有构造器破坏单例。为了解决这个问题,可以在构造器内加一个判断:

    private Singleton() {if (instance != null) {throw new RuntimeException("单例模式被破坏");}
    }
    
  2. 防止序列化破坏单例: 如果单例类实现了 Serializable 接口,在反序列化时可能会创建新的实例。为了解决这个问题,可以在类中实现 readResolve 方法:

    private Object readResolve() {return instance;
    }
    
  3. 线程安全优化: 双重检查锁定(DCL)方式在保证线程安全的前提下,提高了性能,是多线程环境下常用的实现方式。

  4. 枚举单例推荐: 使用枚举实现单例模式可以简化代码,保证线程安全,并且防止反射和序列化破坏单例,因此被认为是最推荐的方式。

单例模式的实际实例

假设我们需要一个日志管理器,该管理器只允许创建一个实例,并能通过全局访问点进行日志记录。

public class LoggerSingleton {private static LoggerSingleton instance;private LoggerSingleton() {}// 双重检查锁定获取单例实例public static LoggerSingleton getInstance() {if (instance == null) {synchronized (LoggerSingleton.class) {if (instance == null) {instance = new LoggerSingleton();}}}return instance;}public void log(String message) {System.out.println("Log: " + message);}
}public class Main {public static void main(String[] args) {LoggerSingleton logger = LoggerSingleton.getInstance();logger.log("This is a singleton logger.");}
}

总结

  • 单例模式提供了确保类实例唯一的有效方案,适用于全局共享资源。
  • 常见实现方式包括懒汉式、双重检查锁定和静态内部类等。
  • 推荐使用枚举实现单例,因为它天然防止了反射和序列化破坏单例的风险。
关键字:【设计模式】单例模式详解及应用实例

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: