1 单例模式
单例模式(Singleton Pattern) 属于 创建型模式. 它提供了一种创建对象的方法.
为什么需要单例模式?
避免一个全局使用的类频繁地创建实例并销毁.
单例模式的关键点:
- 只创建一个实例.
- 实例被
static
关键字修饰(Java). - 类的构造方法是私有的.
实现单例模式主要有3种方法: 饿汉式, 双重检查加锁, 懒汉式.
2 饿汉式
饿汉式 是使用较多的一种方式. 在类加载时就初始化实例.
因为通常我们实例化一个对象都会使用它, 所以提前实例化和使用时再实例化没有什么区别.
当我们不确定实例是否被使用时, 可以考虑使用 双重检查加锁.
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
3 双重检查加锁
双重检查加锁(double-checked locking) 也是常用的一种方式.
在用到实例时再初始化, 可以避免实例化出 不使用的对象, 从而造成内存浪费.
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;
}
}
4 懒汉式
懒汉式 这种 不常用, 主要是在并发时 性能差.
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
5 灵活运用
我们可以写一个 init
方法, 把初始化逻辑放在 init
方法里, 然后在 main
方法(或者服务启动方法)中调用 init
来完成初识化.
这种方式的思想也是 饿汉式. 不过, 当我们的 Singleton
类的构造比较复杂时, 无法在类加载时完成实例化, 就可以采用 init
方法实例化.
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static void init() {
// initialize
INSTANCE = new Singleton();
}
public Singleton getInstance() {
return INSTANCE;
}
}
Reference
[1]. 单例模式-菜鸟教程
[2]. Design Pattern - Singleton Pattern