单身设计模式和防止克隆

时间:2012-02-16 14:31:16

标签: java singleton clone

我在网上看过很多关于Singleton设计模式的文章,提到该类应该覆盖'clone()'方法,并在其中抛出'CloneNotSupported'异常。这真的有必要吗?

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

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

10 个答案:

答案 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方法受到保护,你不能将单例类子类化。