单例模式的5种实现

来源:互联网 发布:工商银行客户端 mac 编辑:程序博客网 时间:2024/06/05 20:32

概要:主要有以下五种,除了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 {        }}
原创粉丝点击