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

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

作者: 没走过的二丁目 | 来源:发表于2018-01-17 15:45 被阅读0次

singleton指仅仅被实例化一次的类,singleton通常被用来代表那些本质上唯一的>系统组件,比如窗口管理器或者文件系统.使类成为singleton会是他的客户端测试变得十分困难,因为无法给singleton替换模拟实现,除非他实现一个充当其类型的接口。

singlton

public class Singleton {
    private static final Singleton SINGLETON = new Singleton();

    private Singleton() {
        if(SINGLETON != null){
            throw new UnsupportedOperationException("instance is exist");
        }
    }
    public static Singleton getInstance(){
        return SINGLETON;
    }
}

由于虽然缺少公有的和受保护的构造器,可以保证全局唯一性,但是享有特权的客户端可以借助AccessibleObject.setAccessible方法,通过反射机制调用私有构造器。于是上述例子中在创建第二个实例的时候抛出异常

  • 关于singleton的序列化后的反序列化
    虽然上述写法已经很强大的可以保证单例,但是在序列化后的反序列化的情况下,会获得一个新的对象,
public class Person {
    public static void main(String[] args) throws  Exception{
        Person person =new Person();
        person.serializableTest();
    }
    public void serializableTest() throws Exception{
        serializable(Singleton.getInstance(), "test");
        Singleton singleton = deserializable("test");
        System.out.println(singleton);
        System.out.print(singleton.getInstance());
    }

//序列化
    private void serializable(Singleton singleton, String filename) throws IOException {
        FileOutputStream fos = new FileOutputStream(filename);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(singleton);
        oos.flush();
    }
//反序列化
    private <T> T deserializable(String filename) throws IOException,ClassNotFoundException {
        FileInputStream fis = new FileInputStream(filename);
        ObjectInputStream ois = new ObjectInputStream(fis);
        return (T) ois.readObject();
    }
}
结果展示.jpg

可以看到这里是两个singleton实例
那么此时要怎么解决呢?答案很简单,只需要在singleton类中添加如下代码即可

private Object readResolve() {
        return SINGLETON;
    }
  • 利用枚举来强化Singleton(最佳方案)
    利用单元素的枚举来实现单例(Singleton),绝对防止多次实例化
public enum SingletonEnum {
        INSTANCE;
        private String name;

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
}

使用

SingletonEnum.INSTANCE.setName("Bob");
System.out.println(SingletonEnum.INSTANCE.getName());

单元素的枚举已经类型已经成为实现Singleton的最佳方法

相关文章

网友评论

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

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