目录
一、介绍
1.定义
确保类只有一个实例,并提供一个全局访问点。
2.角色
- Singleton:单例类
3.特点
- 优点:因为系统内存中只有一个实例,可以节约系统资源,并且减少了因为创建、销毁对象带来的损耗,提高了系统的性能。
- 缺点:该模式没有抽象层,不易于扩展,且违背了“单一职责原则”,既负责实例的创建,又包含了一些业务方法。
二、实现
1.饿汉式(线程安全)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
在加载类时即创建唯一的单例实例,不管用不用,先创建再说。若一直未被使用,则浪费了空间,但因为每次调用时无需判断,节省了运行时间,以空间换时间。
2.懒汉式
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在第一次使用实例时才创建。该方式是线程不安全的,在多个线程同时访问getInstance方法时会出现问题,可在getInstance方法使用synchronized关键字解决该问题。但每次调用该方法时都要先获取锁,可能会增加运行时间,还会造成阻塞。
3.懒汉式(双重检查加锁版本)
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
只有在第一次创建实例时才会进入synchronized块,减少了getInstance方法的运行时间。同时采用了volatile关键字保持数据的可见性以及防止指令重排。
4. 枚举方式
public enum Singleton {
INSTANCE;
public void doSomething() {
}
}
枚举创建实例是线程安全的,因此该方法既简洁又安全,但可读性不高,较少用。
5.静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
在显式调用getInstance方法时才会装载SingletonHolder类,从而初始化实例,因此是线程安全的。
参考:
1. 《Head First 设计模式》
2. 《图说设计模式》 https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/singleton.html