美文网首页
1.3用私有构造器或者枚举类型强化singleton属性

1.3用私有构造器或者枚举类型强化singleton属性

作者: flyjar | 来源:发表于2020-12-07 14:20 被阅读0次

    1.3用私有构造器或者枚举类型强化singleton属性

    1.3.1

    饿汉式和懒汉式,通过反射机制被破解。需要强化校验当构造器被私有化后,程序员的任何行为都不会改变生成,该类只会生成一个实例。但是要注意的是反射机制。程序员可以借助AccessiableObject.setAccessiable方法(设置此方法后,将拥有访问私有属性,方法和构造器的能力),通过反射机制调用私有化的构造器。从而破坏了单例。

    饿汉式,加强代码

     public class Singleton {  
        private final static Singleton instance = new Singleton();  
        private Singleton (){
            //在此处编写加强校验.如果第二次被调用,就抛出异常。这是为了防止被发射调用
             if(instance!=null){
                 throw new RuntimeException("非法创建对象!");
             }
        }  
        public static Singleton getInstance() {  
        return instance;  
        }  
    }
    

    懒汉式---DCL

    public class Instance {
      
        private static Instance ins = null;
       
        private Instance(){
               //在此处编写加强校验.如果第二次被调用,就抛出异常。这是为了防止被发射调用
             if(instance!=null){
                 throw new RuntimeException("非法创建对象!");
             }
        }
        
        /**
         * DCL方式获取单例
         * @return
         */
        public static Instance getInstance(){
             
            if (ins == null){
                //为什么把synchronized加在这层,是提高性能。在多线程的情况,只要ins不为null。完全可以直接返回ins这个对象了。而不需要再去争夺锁。判断ins到底是不是空的。因为ins不是空的情况下,不会再执行生成实例的代码了。
                synchronized (Instance.class){
                    if (ins == null){
                        ins = new Instance();
                    }
                }
            }
            return ins;
        }
        
    }
    

    1.3.2

    饿汉式和懒汉式,通过序列化破解。需要强化代码当单例模式的类型实现了Serializable。对单例进行序列化,再进行反序列化之后,发现了序列化的对象和反序列的对象,不再相等。反序列化之后,又产生了新的对象。从而破坏了序列化。

    懒汉式,加强代码

    public class SingletonSerializable implements Serializable {
    
        private static final long serialVersionUID = -1131868478960947804L;
    
        private static  final SingletonSerializable singletonSerializable = new SingletonSerializable();
    
        private SingletonSerializable(){
           
        }
    
        public static SingletonSerializable getInstance(){
            return singletonSerializable;
        }
    
    }
    

    序列化和反序列化代码

    public class TestSingleton {
        @Test
        public void testEqual() throws Exception{
            //获取到单例对象
            SingletonSerializable instance = SingletonSerializable.getInstance();
            
            //序列化
            FileOutputStream fileOutputStream = new FileOutputStream("temp");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(instance);
    
            //反序列化
            FileInputStream fileInputStream = new FileInputStream("temp");
            ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
            SingletonSerializable o = (SingletonSerializable)objectInputStream.readObject();
    
            //打印结果
            System.out.println(instance == o);  //输入为false
        }
    }
    

    对懒汉式进行代码强化

    public class SingletonSerializable implements Serializable {
    
        private static final long serialVersionUID = -1131868478960947804L;
    
        private static  final SingletonSerializable singletonSerializable = new SingletonSerializable();
    
        private SingletonSerializable(){
           
        }
    
        public static SingletonSerializable getInstance(){
            return singletonSerializable;
        }
    
        //加上此方法之后,序列化和反序化之后的对象将会相等。这里返回对象必须得是Object。这里涉及一些内部原理,不再过多的阐述了
        private Object readResolve(){
            return singletonSerializable;
        }
    }
       
    

    1.3.4

    枚举单例模式,无常的提供了序列化机制,并且不受反射的影响,天然的优势,使得枚举再实现单例模式时,代码更加简洁。更加安全。

    public enum SingletonEnum{
        INSTANCE;
        public void doThing1(){
          
        }
        public void doThing2(){
          
        }
    }
    
    public static void main(String[]args){
       //去调用doThing1方法。
       SingletonEnum.INSTANCE.doThing1();
    }
    

    相关文章

      网友评论

          本文标题:1.3用私有构造器或者枚举类型强化singleton属性

          本文链接:https://www.haomeiwen.com/subject/ncizwktx.html