单例模式是 Java 中一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。单例模式通常用于需要严格控制实例数量,以节省系统资源或保证数据一致性的场景,例如配置管理、数据库连接池等。
实现单例模式的关键要点
- 私有构造函数:防止外部类直接通过
new
关键字创建该类的实例。 - 静态实例变量:在类内部维护一个该类的静态实例。
- 公共静态方法:提供一个公共的静态方法,用于获取该类的唯一实例。
常见的单例模式实现方式
1. 饿汉式(静态常量)
优点:实现简单,线程安全,因为实例在类加载时就已经创建。
缺点:如果该实例在整个程序运行过程中都未被使用,会造成资源浪费。
2. 饿汉式(静态代码块)
优缺点:与静态常量的饿汉式类似,只是实例化过程放在了静态代码块中。
3. 懒汉式(线程不安全)
优点:延迟加载,只有在需要时才创建实例。
缺点:线程不安全,在多线程环境下可能会创建多个实例。
4. 懒汉式(线程安全,同步方法)
优点:线程安全,延迟加载。
缺点:每次调用 getInstance() 方法都需要进行同步,会影响性能。
5. 双重检查锁定(DCL,Double-Checked Locking)
优点:线程安全,延迟加载,性能较高,只有在第一次创建实例时才进行同步。
缺点:实现较为复杂,需要使用 volatile 关键字来防止指令重排序。
6. 静态内部类
优点:线程安全,延迟加载,实现简单。因为静态内部类在外部类被加载时不会被加载,只有在调用 getInstance() 方法时才会加载并创建实例。
7. 枚举
优点:线程安全,可防止反序列化重新创建新的对象,是实现单例模式的最佳方式。
缺点:使用枚举类型可能不太符合传统的类设计思维。
总结
在选择单例模式的实现方式时,需要根据具体的需求和场景来决定。如果对性能要求较高,且不需要延迟加载,可以选择饿汉式;如果需要延迟加载,且在多线程环境下使用,建议选择双重检查锁定或静态内部类的方式;如果需要防止反序列化重新创建对象,枚举是最好的选择。