2012-02-16 95 views
19

我在网上阅读的关于Singleton设计模式的许多文章都提到,类应该重写'clone()'方法,并在其中抛出'CloneNotSupported'异常。这真的有必要吗?Singleton设计模式和防止克隆

默认情况下,clone()方法是受保护的,因此没有类(除了那些在同一个包中的类)将能够在该Singleton实例上调用它。另外,如果这个Singleton没有实现Cloneable,那么即使这个方法被调用,它也会给出一个运行时异常。另外,构造函数是私有的,我们将不能够继承它,从而允许它的克隆。那么我是否应该为我的Singleton类实现这个建议?

编辑:只是为了澄清:我没有寻找最好的方式来实现Singleton。我只是问上面提到的建议的有效性,w'r'是'正常的'Singleton模式(而不是基于Enum的Singleton模式)。

+2

你问:“如果我创建单身走错了路,我不应该做,应该我担心X“。答案是以正确的方式让你的问题没有意义。不,你不必担心这一点。 – 2012-02-16 14:47:17

回答

18

如果你真的要实施一个单身人士,use a one-element enum并停止考虑它。


编辑:只是为了澄清:我不是在寻找实现辛格尔顿尽可能最好的方式。我只是问上面提到的建议的有效性,w'r'是'正常的'Singleton模式(而不是基于Enum的Singleton模式)。

既然你有有效的Java,那么你应该已经知道的隐患和问题Cloneable的。也就是说,如果你要实施单一的“错误”的方式,不,没有任何理由实施Cloneable并覆盖Object#clone()只是抛出CloneNotSupportedExceptionObject#clone()Cloneable接口不存在时已经这样做

+1

+1 - 并购买Josh Bloch出色的[有效Java](http://java.sun.com/docs/books/effective/),其中涵盖了更多内容。 – 2012-02-16 14:35:53

+0

是的,我知道它,并有书。但我的问题是关于这些文章中给出的克隆建议。有没有这种建议有意义的情况? – shrini1000 2012-02-16 14:36:03

+0

既然你不能克隆'enum',否。 – 2012-02-16 14:38:02

2

使用Singleton模式编写类时,一次只能存在该类的一个实例 。因此,该类不得允许制作克隆。

单例模式表示该类只有一个实例存在于程序内部,因此在Clone()方法中引发CloneNotSupportedException是正确的。

+1

如果你在java中使用'enum'创建一个单例,这不是一个问题。 – 2012-02-16 14:40:38

+2

哇,从一枚枚举中剔除单例的年龄被认为是正确的做事方式。 – Perception 2012-02-16 15:09:45

0

只有当您的单例类实现了接口或实现了Cloneable接口的类时,才需要覆盖clone()方法。

2

如果您的Singleton类扩展了在其层次结构中定义了可见的clone()方法的类,那么这是非常必要的。

6

@ shrini1000,你有一个有效的问题,但有关克隆suggetsion是 非常具体如下条件

public Object clone() throws CloneNotSupportedException { 
    throw new CloneNotSupportedException(); 
} 

以上是如果一个单例类的父类实现了一个公共的克隆只需要()方法

+1

Thx Gourabp;但我看到很多例子,其中辛格尔顿不是一个子类,但它明确地阻止克隆,因此我的问题。 – shrini1000 2013-08-07 17:00:02

2

通过使用克隆方法提供已创建的对象,可以避免克隆。

public Object clone() { 

return singletoneObject; 

} 
3

在下面的代码是用于防止单例类是cloned.Override克隆方法和抛出新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(); 
     } 
    } 

} 
+0

默认情况下,clone()方法被标记为受保护的,但是如果SingletonObject扩展了另一个支持克隆的类,则可能违反单例的设计原则。因此,为了绝对肯定单身人士确实是单身人士,我们必须添加我们自己的clone()方法,并且如果有人敢尝试抛出CloneNotSupportedException! – 2016-05-13 08:27:46

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:[email protected] 
Singleton clone:[email protected] 
0

根据我的理解,你不需要实现clone()方法。原因: 1.如果您未实现克隆方法和Cloneable接口,它将引发CloneNotSupportedException。 2.克隆方法受保护,您不能继承一个单例类。