单例模式的5种实现

概要:主要有以下五种,除了4和5 ,安全与否取决于是否加synchronized关键字,加了之后肯定对效率肯定有影响

  1. 懒汉
  2. 饿汉
  3. 二次检查
  4. 静态内部类(只加载一次)

    以上四种都存在2个问题

    1. 会被反射的setAccessible(true)破坏单例模式;
    2. 反序列化时会破坏单例

    解决方式如下:

  5. 单元素枚举(最优)

 //懒汉
 class LazySingleton{
     private static LazySingleton singLeton = new LazySingleton(); 
     private LazySingleton(){

     }
     public synchronized LazySingleton getLazySingleton(){
         if(singLeton==null){
             return new LazySingleton();
         }
         return singLeton;
     }
 }
 //饿汉
 class HunSingleton{
     //安全,但类加载时就初始化
     private static HunSingleton singleton = new HunSingleton();
     private HunSingleton(){}
     public static HunSingleton getHunSinglelton(){
         return singleton;
     }
 }
 //双重校验
 class DoubleCheckSingleton{
     private static DoubleCheckSingleton singleton;
     private DoubleCheckSingleton(){}
     public static DoubleCheckSingleton getHunSinglelton(){
         if(singleton==null){
             synchronized(DoubleCheckSingleton.class){
             //第二次判断的目的是在第一次判断的时候创建了对象
             //第一次判断是为了效率
                 if(singleton==null){
                     return new DoubleCheckSingleton();
                 }
             }
         }
         return singleton;
     }
 }
 //静态内部类
 class ClazzSingleton{
     private ClazzSingleton(){};
     public ClazzSingleton getSingleton(){
         return InnerClazz.singleton;
     }
     static class InnerClazz{
         private static ClazzSingleton singleton = new ClazzSingleton();
 }
//用于解决反序列化后 对象不一致的问题,直接在类里加一下方法:

private Object readResolve(){
    return singleton;
}
//解决被反射破坏单例的问题:在构造函数中增加次数验证,类似于List中的madCount
 private Demo() throws Exception{
     if(madCount!=0){
         throw new Exception("创建过对象");
     }
     madCount++;
 }
 //单元素枚举
 enum EnumSingleton{
     INSTANCE;
     public void show(){
         System.out.println("Ea");
     }
 }
 //利用反射破坏单例模式
 public void destroy(){
        try {
            Constructor<Demo> coo = Demo.class.getDeclaredConstructor();
            //此处设置权限
            coo.setAccessible(true);
            Demo d = coo.newInstance();
            Demo e = coo.newInstance();
            System.out.println(d==e);//false
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值