单例模式
1 概述
- 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
- 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。
- 注意:
- 1)单例类只能有一个实例。
- 2)单例类必须自己创建自己的唯一实例。
- 3)单例类必须给所有其他对象提供这一实例。
2 优缺点及应用场景
2.1 优点
- 1)唯一实例:保证系统中只有一个实例,避免不一致的状态。
- 2)全局访问:提供一个全局访问点,方便获取实例。
- 3)序列号:生成唯一序列号。
2.2 缺点
- 1)不易扩展:单例模式对扩展不友好,难以进行子类化。
- 2)隐藏依赖:使代码与全局实例耦合,增加了代码的复杂性和难以测试性。
2.3 应用场景
- 1)日志记录器:日志记录器通常作为单例存在,以确保日志信息的一致性和顺序性,同时避免多实例导致的资源竞争。
- 2)配置管理器:在应用程序中,配置管理器通常只需要一个实例,用于存储和访问应用程序的配置信息。
3 结构
- 1)单例类:包含单例实例的类,通常将构造函数声明为私有。
- 2)静态成员变量:用于存储单例实例的静态成员变量。
- 3)获取实例方法:静态方法,用于获取单例实例。
- 4)私有构造函数:防止外部直接实例化单例类。
- 5)线程安全处理:确保在多线程环境下单例实例的创建是安全的。
4 实现
4.1 UML 类图

4.2 代码示例
4.2.1 单例模式(java 双重判空加锁)
public class SingletonPattern1 {
private static volatile SingletonPattern1 instance = null;
private SingletonPattern1() {
}
public static SingletonPattern1 getInstance() {
if (null == instance) {
synchronized (SingletonPattern1.class) {
if (null == instance) {
instance = new SingletonPattern1();
}
}
}
return instance;
}
}
4.2.2 单例模式(java 静态代码块)
public class SingletonPattern2 {
private SingletonPattern2() {
}
private static class Holder {
public static SingletonPattern2 instance = new SingletonPattern2();
}
public static SingletonPattern2 getInstance() {
return Holder.instance;
}
}
4.2.3 单例模式(kotlin 双重判空加锁)
class SingletonPattern3 private constructor() {
companion object {
@Volatile
private var instance: SingletonPattern3? = null
@JvmStatic
fun getInstance(): SingletonPattern3 {
return instance ?: synchronized(this) {
instance ?: SingletonPattern3().also {instance = it}
}
}
}
}
4.2.4 单例模式(kotlin 静态代码块)
class SingletonPattern4 private constructor() {
companion object {
val instance = Holder.instance
}
private object Holder {
val instance = SingletonPattern4()
}
}
4.2.4 单例模式(kotlin by lazy)
class SingletonPattern5 private constructor() {
companion object {
val instance: SingletonPattern5 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {SingletonPattern5()}
}
}
4.2.5 单例模式验证 Demo
public class SingletonPatternDemo {
public static void main(String[] args) {
SingletonPattern1 single1_1 = SingletonPattern1.getInstance();
SingletonPattern1 single1_2 = SingletonPattern1.getInstance();
System.out.println("Inside hashCode isTrue:" + (single1_1.hashCode() == single1_2.hashCode()));
SingletonPattern2 single2_1 = SingletonPattern2.getInstance();
SingletonPattern2 single2_2 = SingletonPattern2.getInstance();
System.out.println("Inside hashCode isTrue:" + (single2_1.hashCode() == single2_2.hashCode()));
SingletonPattern3 single3_1 = SingletonPattern3.Companion.getInstance();
SingletonPattern3 single3_2 = SingletonPattern3.Companion.getInstance();
System.out.println("Inside hashCode isTrue:" + (single3_1.hashCode() == single3_2.hashCode()));
SingletonPattern4 single4_1 = SingletonPattern4.Companion.getInstance();
SingletonPattern4 single4_2 = SingletonPattern4.Companion.getInstance();
System.out.println("Inside hashCode isTrue:" + (single4_1.hashCode() == single4_2.hashCode()));
SingletonPattern5 single5_1 = SingletonPattern5.Companion.getInstance();
SingletonPattern5 single5_2 = SingletonPattern5.Companion.getInstance();
System.out.println("Inside hashCode isTrue:" + (single5_1.hashCode() == single5_2.hashCode()));
}
}
- 执行程序,输出结果:
```java
Inside Inside hashCode isTrue: true.
Inside Inside hashCode isTrue: true.
Inside Inside hashCode isTrue: true.
Inside Inside hashCode isTrue: true.
Inside Inside hashCode isTrue: true.
5 总结
- 单例模式通过确保类只有一个实例,并提供一个全局访问点,适用于需要全局唯一实例的场景。虽然简单易用,但需要注意其潜在的缺点,如不易扩展和隐藏依赖。在实际应用中,需根据具体情况权衡使用单例模式带来的利弊。