2012-02-16 338 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.克隆方法受保護,您不能繼承一個單例類。