设计模式_单例设计模式_破坏以及解决
原创
©著作权归作者所有:来自51CTO博客作者959_1x的原创作品,请联系作者获取转载授权,否则将追究法律责任
破坏有两种:
1.序列化和反序列化
2.反射机制
class Single7{
private Single7(){
}
private static class SingletonInstance{
private static final Single7 INSTANCE = new Single7();
}
public static Single7 getInstance(){
return SingletonInstance.INSTANCE;
}
}
1.序列化和反序列化破坏单例模式
public class Client {
public static void main(String[] args) throws Exception {
// writeObject2File();
readObjectFromFile();
readObjectFromFile();
}
//向文件中写数据
public static void writeObject2File()throws Exception{
//1.获取对象
Single7 instance = Single7.getInstance();
//2.创建输出对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\a.txt"));
//写数据
oos.writeObject(instance);
oos.close();
}
//向文件中读取数据
public static void readObjectFromFile()throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\a.txt"));
Single7 single7 = (Single7)ois.readObject();
System.out.println(single7);
ois.close();
}
}
先执行writeObject2File();
然后执行 readObjectFromFile();两边
打印出对象的地址发现不同

解决方案:
class Single7 implements Serializable {
private static boolean flag = false;
private Single7() {
}
public static Single7 getInstance() {
return Singletoninstance.INSTANCE;
}
private static class Singletoninstance {
private static final Single7 INSTANCE = new Single7();
//反序列化时候,自动调用该方法,将该方法的返回值自动返回
public Object readResolve() {
return Singletoninstance.INSTANCE;
}
}
}
加入
public Object readResolve() {
return Singletoninstance.INSTANCE;
}
原因要分析序列化的方法readObject底层方法的调用:

所以如果加入上面的readResovle方法的话
反序列化时候,自动调用该方法,将该方法的返回值自动返回
2.反射破坏单例模式
public class Client2 {
public static void main(String[] args) throws Exception{
Class clazz = Single7.class;
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Single7 o = (Single7)constructor.newInstance();
Single7 o2 = (Single7)constructor.newInstance();
System.out.println(o == o2);
}
}
输出

解决方案
class Single7 implements Serializable {
private static boolean flag = false;
private Single7() {
synchronized (Single7.class) {
}
if (flag) {
throw new RuntimeException("不可以创建多个对象");
}
flag = true;
}
public static Single7 getInstance() {
return Singletoninstance.INSTANCE;
}
private static class Singletoninstance {
private static final Single7 INSTANCE = new Single7();
}
}
加入了一个flag判断是否单例
然后通过一个synchronize锁来控制线程安全问题。
输出为
