我在网上看过很多关于Singleton设计模式的文章,提到该类应该覆盖'clone()'方法,并在其中抛出'CloneNotSupported'异常。这真的有必要吗?
默认情况下,clone()方法是受保护的,因此没有类(同一个包中的类除外)能够在该Singleton实例上调用它。另外,如果这个Singleton没有实现Cloneable,那么即使调用了这个方法,它也会产生运行时异常。另外,构造函数是私有的,我们将无法对其进行子类化,从而允许进行克隆。那么我还应该为我的Singleton类实现这个建议吗?
编辑:只是为了澄清:我不是在寻找实现Singleton的最佳方法。我只是询问上面提到的建议的有效性,w.r.t'正常'的Singleton模式(而不是基于Enum的Singleton)。
答案 0 :(得分:24)
如果你真的要实现一个单身人士,use a one-element enum并且不再考虑它。
编辑:只是为了澄清:我不是在寻找实现Singleton的最佳方法。我只是询问上面提到的建议的有效性,w.r.t'正常'的Singleton模式(而不是基于Enum的Singleton)。
由于你有 Effective Java,,那么你应该已经意识到Cloneable
的缺陷和问题。也就是说,如果你要以“错误”的方式实现单例,那么,实现Cloneable
并覆盖Object#clone()
只是为了抛出CloneNotSupportedException
是绝对没有理由的。当Object#clone()
界面不存在时, Cloneable
已经执行此操作。
答案 1 :(得分:8)
@ shrini1000,你有一个有效的问题,但有关克隆的建议是 非常具体的以下条件
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
上述仅在单例类的超类实现公共clone()方法时才有必要。
答案 2 :(得分:3)
以下代码用于防止克隆单例类。取消克隆方法并抛出新的CloneNotSupportedException()
public final class SingeltonCloneTest implements Cloneable {
/**
* @param args
* @return
*/
private static SingeltonCloneTest instance = null;
private SingeltonCloneTest() {
System.out.println("Rahul Tripathi");
}
public static SingeltonCloneTest getInstance() {
if (instance == null) {
instance = new SingeltonCloneTest();
return instance;
}
return instance;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
/*
* Here forcibly throws the exception for preventing to be cloned
*/
throw new CloneNotSupportedException();
// return super.clone();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SingeltonCloneTest test1 = SingeltonCloneTest.getInstance();
try {
SingeltonCloneTest test2 = (SingeltonCloneTest) test1.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 3 :(得分:2)
有关实施Singleton模式的最安全方法,请参阅https://stackoverflow.com/a/71399/385478。从本质上讲,使用单enum
值使您的单身人士成为class
而不是INSTANCE
。
答案 4 :(得分:2)
使用Singleton模式编写类时,只有一个实例 那个班可以一次存在。结果,班级一定不能 允许制作克隆。
单例模式表示程序中只存在该类的一个实例,因此在Clone()方法中引发CloneNotSupportedException是正确的。
答案 5 :(得分:2)
如果您的Singleton类扩展了一个在其层次结构中定义了可见clone()方法的类,那么这是必要的。
答案 6 :(得分:2)
您可以通过克隆方法提供已创建的对象来避免克隆。
public Object clone() {
return singletoneObject;
}
答案 7 :(得分:1)
我发现的最好的例子是:
class SingletonSuper implements Cloneable {
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Singleton2 extends SingletonSuper {
// 1. Make all constructors private
private Singleton2() {
}
// 2. Declare a private static variable to hold single instance of class
private static Singleton2 INSTANCE = new Singleton2();
public static Singleton2 getInstance() {
return INSTANCE;
}
}
public class SingletonCloningTest {
public static void main(String[] args) throws Exception {
System.out.println("Singleton Test!");
System.out.println("Singleton Instance:" + + Singleton2.getInstance());
System.out.println("Singleton clone:"
+ Singleton2.getInstance().clone());
}
}
The result will:
Singleton Test!
Singleton Instance:com.sample.test.Singleton2@50d89c
Singleton clone:com.sample.test.Singleton2@1bd0dd4
答案 8 :(得分:0)
只有当您的单例类实现clone()
接口或实现Cloneable
接口的类时,才需要覆盖Cloneable
方法。
答案 9 :(得分:0)
根据我的理解,您不需要实现clone()方法。原因: 1.如果您没有实现克隆方法和Cloneable接口,它将抛出CloneNotSupportedException。 2. clone方法受到保护,你不能将单例类子类化。