设计模式-单例模式

核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点,减少了系统性能开销。
常见应用场景:Windows的任务管理器就是很典型的单例模式;数据库连接池的设计一般也是采用单例模式…
常见的五种单例模式实现方式:
1.饿汉式:线程安全,调用效率高。 但是,不能延时加载;
2.懒汉式:线程安全,调用效率不高,可以延时加载;
3.静态内部类式:线程安全,调用效率高,可以延时加载;
4.枚举式:线程安全,调用效率高,不能延时加载。并且可以天然的防止反射和反序列化创建对象的漏洞!
5.双重检测锁式:JVM底层内部模型原因,偶尔会出问题。不建议使用;

饿汉式:

1
2
3
4
5
6
7
8
9
10
11
//饿汉式:
public class SingletonDemo01 {
//类初始化时,上来先创建对象(没有延时加载的优势),加载类时,天然线程安全
private static SingletonDemo01 instance = new SingletonDemo01();
//构造器私有
private SingletonDemo01(){}
//优点:方法没有同步调用效率高
public static SingletonDemo01 getInstance(){
return instance;
}
}

懒汉式:

1
2
3
4
5
6
7
8
9
10
11
12
//懒汉式:
public class SingletonDemo02 {
//类初始化时,不创建对象(延时加载,真正用的时候再创建)
private static SingletonDemo02 instance;
//构造器私有
private SingletonDemo02(){}
//需要加同步,保证单例模式,效率较低
public static synchronized SingletonDemo02 getInstance(){
if(instance == null) instance = new SingletonDemo02();
return instance;
}
}

静态内部类式:

1
2
3
4
5
6
7
8
9
10
11
12
//静态内部类方式:线程安全,调用效率高,实现延时加载
public class SingletonDemo03 {
private static class SingletonInnerClass{
private static final SingletonDemo03 instance = new SingletonDemo03();
}
//构造器私有
private SingletonDemo03(){}
//优点:方法没有同步调用效率高
public static SingletonDemo03 getInstance(){
return SingletonInnerClass.instance;
}
}

枚举式:

1
2
3
4
5
6
7
//枚举类方式:线程安全,但没有延时加载;同时能够避免反射和反序列的漏洞
public enum SingletonDemo04 {
INSTANCE;
//可以自己添加一些操作方法
public static void instanceOper(){
}
}

如何选用合适的单例模式:
单例对象占用资源少,不需要延时加载:枚举式 > 饿汉式;
单例对象占用资源大,需要 延时加载:静态内部类式 > 懒汉式;