设计模式——创建型之单例模式
一个类自我实例化,不对外暴露实例化接口,且保证对外提供的实例相同,这种创建对象的模式叫单例模式
单例模式减少了全局对象的创建和销毁次数,节省系统资源
1、实现方式
在类加载时就创建实例
1.1、饿汉式
1.1.1、普通实现
public class Hungry {
//1、通过类加载的双亲委派模型,保证初始化单一实例
private static Hungry instance = new Hungry();
//2、限制构造函数私有化,保证外部无法构造新实例
private Hungry(){}
public static Hungry getInstance(){
return instance;
}
}
Hungry instance = Hungry.getInstance()
1.1.2、枚举
public enum EnumClass {
INSTANCE;
}
EnumClass instance = EnumClass.INSTANCE;
1.2、懒汉式
使用时才创建类实例
1.2.1、双重检测
public class Lazy {
//1、类加载时并不初始化实例
private static Lazy instance;
//2、限制构造函数私有化,保证外部无法构造新实例
private Lazy(){}
//3.1、如果synchronized修饰getInstance方法,无论实例是否创建都会加锁,影响性能,所以放在方法体中
//3.2、如果不在内层进行实例判空,多个线程可能会同时通过外层判空直接创建实例,导致单例失效,所以采用两次判空
public static Lazy getInstance(){
if(instance == null){
synchronized (Lazy.class){
if(instance == null){
instance = new Lazy();
}
}
}
return instance;
}
}
Lazy instance = Lazy.getInstance();
1.2.2、静态内部类
public class StaticInnerClass {
//1.1、外部类加载时,内部类并不会一起加载,保证实例懒加载
private static class StaticInnerClassHolder{
private static StaticInnerClass instance = new StaticInnerClass();
}
private StaticInnerClass(){}
public static StaticInnerClass getInstance(){
return StaticInnerClass.getInstance();
}
}
StaticInnerClass instance = StaticInnerClass.getInstance();
2、唯一性
传统的单例对象是进程内(应用)唯一的
实现线程内唯一可以使用ThreadLocal
实现进程间(集群、分布式)唯一可以将对象序列化并加分布式锁