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

2018-01-17  本文已影响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方法,通过反射机制调用私有构造器。于是上述例子中在创建第二个实例的时候抛出异常

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;
    }
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的最佳方法

上一篇 下一篇

猜你喜欢

热点阅读