Java 单例设计模式与防止克隆
我在网上读到的许多关于单例设计模式的文章都提到该类应该重写“clone()”方法,并在其中抛出“CloneNotSupported”异常。这真的有必要吗 clone()方法在默认情况下是受保护的,因此任何类(同一包中的类除外)都无法在该单例实例上调用它。另外,如果这个单例没有实现Cloneable,那么即使调用了这个方法,它也会给出一个运行时异常。另外,构造函数是私有的,我们将无法对其进行子类化,从而允许对其进行克隆。那么,我是否应该为我的单例类实现这个建议呢Java 单例设计模式与防止克隆,java,singleton,clone,Java,Singleton,Clone,我在网上读到的许多关于单例设计模式的文章都提到该类应该重写“clone()”方法,并在其中抛出“CloneNotSupported”异常。这真的有必要吗 clone()方法在默认情况下是受保护的,因此任何类(同一包中的类除外)都无法在该单例实例上调用它。另外,如果这个单例没有实现Cloneable,那么即使调用了这个方法,它也会给出一个运行时异常。另外,构造函数是私有的,我们将无法对其进行子类化,从而允许对其进行克隆。那么,我是否应该为我的单例类实现这个建议呢 编辑:只是澄清一下:我不是在寻找实
编辑:只是澄清一下:我不是在寻找实现单例的最佳方法。我只是想问一下上述建议的有效性,即“正常”的单例模式(而不是基于枚举的单例)。如果您真的要实现单例,请不要再考虑它
编辑:只是澄清一下:我不是在寻找实现单例的最佳方法。我只是想问一下上面提到的建议的有效性,w.r.t“正常”单例模式(而不是基于枚举的单例) 既然您拥有高效的Java,那么您应该已经意识到
Cloneable
的缺陷和问题。这就是说,如果你打算用一种“错误”的方式实现一个单例,那么绝对没有理由实现Cloneable
并覆盖Object\#clone()
,只是为了抛出CloneNotSupportedException
Object#clone()
在缺少Cloneable
接口时已经执行了此操作。请参阅以获取强制执行单例模式的最安全方法。本质上,使用一个实例
值将您的单例设置为枚举
而不是类
使用Singleton模式编写类时,只有
该类可以同时存在。因此,该类不能
允许进行克隆
singleton模式表示程序中只存在一个类实例,因此在Clone()方法中引发CloneNotSupportedException是正确的。您需要重写
Clone()
方法,仅当您的singleton类实现了Cloneable
接口或实现了Cloneable
接口的类时。如果您的singleton类扩展了在其层次结构中定义了可见clone()方法的类,则有必要使用该方法。@shrini1000,您有一个有效的问题,但有关克隆的建议是
非常特定于以下情况
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
只有当singleton类的超类实现公共clone()方法时,才需要执行上述操作您可以通过按clone方法提供已创建的对象来避免克隆
public Object clone() {
return singletoneObject;
}
下面的代码用于防止克隆singleton类。重写clone方法并抛出新的CloneNotSupportedException()
我发现的最好的例子是:
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
根据我的理解,您不需要实现clone()方法。原因: 1.如果您不实现clone方法和Cloneable接口,它将抛出CloneNotSupportedException。
2.克隆方法是受保护的,您不能对单例类进行子类化。+1-购买Josh Bloch的《优秀》一书,其中涵盖了这一点和更多内容。是的,我知道这一点,并且有这本书。但我的问题是关于这些文章中给出的克隆建议。在任何情况下,这个建议都是有意义的吗?既然你不能克隆
enum
,不@shrini1000为什么你会听取关于不相关实现的建议?@MΓΓББLL我只是想弄清楚给出这些建议背后的思考过程,如果你在java中使用enum
以正确的方式创建一个单例,这不是问题。哇,在这个时代,从enum中删除一个单例被认为是做事情的正确方式。你是在问“如果我以错误的方式创建单例,我不应该这样做,我应该担心X吗答案是用正确的方法去做,这样你的问题就没有意义了。不,你不必担心这个;但是我看到过很多例子,其中Singleton不是一个子类,但它明确地阻止了克隆,因此我提出了问题。默认情况下,clone()方法被标记为受保护,但是如果您的Singleton对象扩展了另一个支持克隆的类,则可能会违反Singleton的设计原则。因此,要绝对100%肯定一个singleton真的是一个singleton,我们必须添加一个我们自己的clone()方法,如果有人敢尝试,我们必须抛出CloneNotSupportedException!
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