单例模式详解

单例模式

1. 单例特点:

  • 单例类只有一个实例对象
  • 该单例对象必须有单例类自行创建
  • 单例类对外提供一个访问该单例的全局访问点

2. 实现方式

  1. 饿汉式
    优点: 线程安全,在类加载时创建一个实例,调用反应速度快。
    缺点: 资源利用率不高,可能getInstance()永远执行不到,但是调用该类的其他静态方法或者加载该类,仍然会实例化对象,浪费空间。
    代码示例:
//饿汉式
public class HungrySingleton {

    //私有静态单例对象
    private static HungrySingleton singleton = new HungrySingleton();
    //提供公共静态方法,以供外部访问
    public static HungrySingleton getInstance(){
        return singleton;
    }
    //构造方法私有,避免外部new实例
    private HungrySingleton() {
    }
}
  1. 懒汉式
    优点: 延迟加载,不浪费空间
    缺点: 线程不安全
    代码示例:
public class LazySingleTon {

    //私有静态单例对象
    private static LazySingleTon singleTon;
    //提供公共静态方法,以供外部访问
    public static LazySingleTon getInstance(){
        if(singleTon == null){
            singleTon = new LazySingleTon();
        }
        return singleTon;
    }
    //构造方法私有,避免外部new实例
    private LazySingleTon(){

    }
}
  1. 双重校验锁
    优点: 延迟加载,线程安全
    缺点: 第一次使用加载不够快,多线程调用不必要的同步开销大
    代码示例:
public class DoubleCheckSingleTon {
    //私有静态单例对象
    private static DoubleCheckSingleTon singleTon;
    //提供公共静态方法,以供外部访问
    public static DoubleCheckSingleTon getInstance(){
        if(singleTon == null){
            synchronized (DoubleCheckSingleTon.class){
                if(singleTon == null){
                    singleTon = new DoubleCheckSingleTon();
                }
            }
        }
        return singleTon;
    }
    //构造方法私有,避免外部new实例
    private DoubleCheckSingleTon() {
    }
}
  1. 静态内部类
    优点: 线程安全,在类加载时创建一个实例,效率高
    缺点: 资源利用率不高,可能getInstance()永远执行不到,但是调用该类的其他静态方法或者加载该类,仍然会实例化对象,浪费空间。
    代码示例:
public class StaticSingleTon {

    //静态内部类
    private static class Inner{
        //私有静态单例对象
        private static StaticSingleTon SINGLETON = new StaticSingleTon();
    }
    //提供公共静态方法,以供外部访问
    private static StaticSingleTon singleTon(){
        return Inner.SINGLETON;
    }
    //构造方法私有,避免外部new实例
    private StaticSingleTon() {
    }
}
  1. 枚举(推荐)
    优点: 天然线程安全,无需锁,简洁,反射/序列化不会破坏单例
    缺点: 不可继承,不能延迟加载
    代码示例:
public class EnumSingleTon {

    //枚举类
    private static enum Singleton{
        SINGLETON;
        //私有静态单例对象
        private final EnumSingleTon singleTon;
        private Singleton(){
            singleTon = new EnumSingleTon();
        }
        private EnumSingleTon getInstance(){
            return singleTon;
        }
    }
    //提供公共静态方法,以供外部访问
    public static EnumSingleTon getInstance(){
        return Singleton.SINGLETON.singleTon;
    }
    //构造方法私有,避免外部new实例
    private EnumSingleTon() {
    }
}

防止单例被破坏

1. 反射
解决方案:在构造方法中加判断
示例:

private TestDestory(){
        //防止反射破坏单例
        if(singleTon != null){
            throw new RuntimeException("此举会破坏单例!!!");
        }
    }

2. 序列化
解决方案:单例类中添加readResolve方法
示例:

//防止序列化破坏单例
private Object readResolve(){
    return singleTon;
}

3. 克隆
解决方案:重写克隆方法,直接返回单例对象
示例:

//防止克隆破坏单例
@Override
protected Object clone() throws CloneNotSupportedException{
    return singleTon;
}

参考: https://www.kaikeba.com/open/item?lpsc=249750

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值