一.通过序列化来破坏单例模式
在java中,对象的序列化与反序列化是通过readObject和writeObject来实现的
1.序列化的前提
被序列化的类必须实现Serializable接口
定义一个序列化方法
private static <T> void serialize(Object obj, Class<T> clazz) {
String fileName = "singleton";
try {
/**
* 将对象数据写入到文件中
*/
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(fileName));
objectOutputStream.writeObject(obj);
objectOutputStream.close();
/**
* 通过文件将对象读取出来
*/
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(fileName));
T newInstance = (T) objectInputStream.readObject();
objectInputStream.close();
System.out.println("instance:"+obj);
System.out.println("newInstance"+newInstance);
System.out.println(obj == newInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
测试代码:
public static void main(String[] args) {
HungrySingleton instance = HungrySingleton.getInstance();
serialize(instance, HungrySingleton.class);
}
如果HungrySingleton这个类不实现Serialize方法,那么会抛出以下异常:
java.io.NotSerializableException: com.shixinke.practise.design.pattern.content.creation.singleton.HungrySingleton
改造HungrySingleton,使之实现序列化
/**
* 饿汉式
* @author shixinke
*/
public class HungrySingleton implements Serializable {
private static final HungrySingleton INSTANCE = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return INSTANCE;
}
}
2.在被序列化的类加上readResolve方法
/**
* 饿汉式
* @author shixinke
*/
public class HungrySingleton implements Serializable {
private static final HungrySingleton INSTANCE = new HungrySingleton();
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return INSTANCE;
}
private Object readResolve() {
return INSTANCE;
}
}
Q:为什么要定义readResolve方法呢?
A: 这个还得从readObject这个方法说起,readObject会根据对象的类型来执行不同的操作,对于Object对象,那它会查找是否有readResolve这个方法,如果存在,则执行它
二.通过反射来破坏单例模式
1.通过反射创建新的对象
虽然原类中的构造方法是私有的,但是反射是无所不能的
/**
* 通过反射来破坏单例模式
* @author shixinke
*/
public class ReflectDestroy {
private static <T> void reflect(Object instance, Class<T> clazz) {
try {
Constructor constructor = clazz.getDeclaredConstructor();
/**
* 将构造方法设置成可访问的
*/
constructor.setAccessible(true);
T newInstance = (T) constructor.newInstance();
System.out.println("instance:" + instance);
System.out.println("newInstance:" + newInstance);
System.out.println(instance == newInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
HungrySingleton instance = HungrySingleton.getInstance();
reflect(instance, HungrySingleton.class);
}
}
2.在构造方法中判断是否被实例化,抛出异常
/**
* 饿汉式
* @author shixinke
*/
public class HungrySingleton implements Serializable {
private static final HungrySingleton INSTANCE = new HungrySingleton();
private HungrySingleton() {
/**
* 添加判断
*/
if (INSTANCE != null) {
throw new RuntimeException("单例类不能被反射");
}
}
public static HungrySingleton getInstance() {
return INSTANCE;
}
private Object readResolve() {
return INSTANCE;
}
}