原型模式对单例模式的破坏
- 利用反射调用单例类的 clone() 方法,获得单例类的多个实例;
public class HungrySingleton implements Cloneable{
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton() {}
public static HungrySingleton getInstance() {
return hungrySingleton;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String[] args) throws Exception{
HungrySingleton hungrySingleton = HungrySingleton.getInstance();
Method method = HungrySingleton.class.getDeclaredMethod("clone");
method.setAccessible(true);
HungrySingleton cloneHungrSingleton = (HungrySingleton)method.invoke(hungrySingleton);
System.out.println(hungrySingleton);
System.out.println(cloneHungrSingleton);
System.out.println(hungrySingleton == cloneHungrSingleton);
}
}
输出:
designpattern.creational.prototype.singletonattack.HungrySingleton@5b6f7412
designpattern.creational.prototype.singletonattack.HungrySingleton@27973e9b
false
解决方案
- 在 clone() 方法中直接调用 getInstance() 方法;
public class HungrySingleton implements Cloneable{
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton() {}
public static HungrySingleton getInstance() {
return hungrySingleton;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return getInstance();
}
}
public class Test {
public static void main(String[] args) throws Exception{
HungrySingleton hungrySingleton = HungrySingleton.getInstance();
Method method = HungrySingleton.class.getDeclaredMethod("clone");
method.setAccessible(true);
HungrySingleton cloneHungrSingleton = (HungrySingleton)method.invoke(hungrySingleton);
System.out.println(hungrySingleton);
System.out.println(cloneHungrSingleton);
System.out.println(hungrySingleton == cloneHungrSingleton);
}
}
输出:
designpattern.creational.prototype.singletonattack.HungrySingleton@5b6f7412
designpattern.creational.prototype.singletonattack.HungrySingleton@5b6f7412
true