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();
}
}

可以看到这里是两个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的最佳方法
网友评论