本文介绍了单例模式及其4种推荐写法(饿汉模式,双重校验锁(DCL),Holder模式(静态内部类)和枚举模式)和3类保护手段(反序列化,反射,自定义类加载器)
文章目录
单例模式(Singleton Pattern)的定义:
Ensure a class has only one instance,and provide a global point of access to it.
确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例.
使用单例模式的优点
- 节省内存
- 减少性能开销
- 避免对资源的多重占用
单例模式的使用场景
- 无状态的工具类:比如日志工具类,不管是在哪里使用,我们需要的只是它帮我们记录日志信息,除此之外,并不需要在它的实例对象上存储任何状态,这时候我们就只需要一个实例对象即可。
- 全局信息类:比如我们在一个类上记录网站的访问次数,我们不希望有的访问被记录在对象A上,有的却记录在对象B上,这时候我们就让这个类成为单例。
- 实例化需要消耗过多资源的类
- 要求生成唯一序列化的环境
值得注意的是,单例往往都可以通过直接声明为static来实现,把一个实例方法变成静态方法,或者把一个实例变量变成静态变量,都可以起到单例的效果。这只是面向对象和面向过程的区别。
单例模式的4种推荐写法
这里列举了单例模式的4种安全的推荐写法,另外也可以直接在获取单例的方法上加synchronized,这种方法虽然安全但效率极低,不值得推荐.这里4种推荐写法分别为饿汉模式,双重校验锁(DCL),Holder模式(静态内部类)和枚举模式.
1. 饿汉模式
public class Singleton {
private final static Singleton INSTANCE= new Singleton ();
private Singleton () {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
- 原理:通过类加载机制来保证单例,在类被加载的时候创建INSTANCE对象
- 优点:较简单
- 缺点:导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。
2.双重校验锁(DCL)
public class Singleton {
private volatile static Singleton instance = null;
private Singleton () {
}
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton