Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 单例设计模式与防止克隆_Java_Singleton_Clone - Fatal编程技术网

Java 单例设计模式与防止克隆

Java 单例设计模式与防止克隆,java,singleton,clone,Java,Singleton,Clone,我在网上读到的许多关于单例设计模式的文章都提到该类应该重写“clone()”方法,并在其中抛出“CloneNotSupported”异常。这真的有必要吗 clone()方法在默认情况下是受保护的,因此任何类(同一包中的类除外)都无法在该单例实例上调用它。另外,如果这个单例没有实现Cloneable,那么即使调用了这个方法,它也会给出一个运行时异常。另外,构造函数是私有的,我们将无法对其进行子类化,从而允许对其进行克隆。那么,我是否应该为我的单例类实现这个建议呢 编辑:只是澄清一下:我不是在寻找实

我在网上读到的许多关于单例设计模式的文章都提到该类应该重写“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