2012-02-16 14 views
19

Molti articoli che ho letto in Rete sul modello di progettazione Singleton menzionano che la classe dovrebbe sovrascrivere il metodo 'clone()' e al suo interno lanciare l'eccezione 'CloneNotSupported'. E 'davvero necessario?Modello di progettazione di Singleton e prevenzione della clonazione

Il metodo clone() per impostazione predefinita è protetto, quindi nessuna classe (eccetto quelle nello stesso pacchetto) sarà in grado di chiamarla su quell'istanza Singleton. Inoltre, se questo Singleton non implementa Cloneable, anche se questo metodo viene chiamato, darà un'eccezione di runtime. Inoltre, essendo il costruttore privato, non saremo in grado di suddividerlo e quindi consentirne la clonazione. Quindi dovrei ancora implementare questo consiglio per le mie lezioni Singleton?

EDIT: Giusto per chiarire: non sto cercando il modo migliore per implementare Singleton. Sto solo chiedendo la validità del consiglio di cui sopra, w.r.t il normale modello Singleton (e non Singleton basato su Enum).

+2

Stai chiedendo "Se sto creando single nel modo sbagliato, che io non dovrei fare, dovrebbe Sono preoccupato per X ". La risposta è farlo nel modo corretto che rende la tua domanda discutibile. No, non devi preoccuparti di questo. –

risposta

18

Se hai intenzione di implementare un singleton, use a one-element enum e smettere di pensarci.


EDIT: Giusto per chiarire: non sto cercando il modo migliore per implementare Singleton. Sto solo chiedendo la validità del consiglio di cui sopra, w.r.t il normale modello Singleton (e non Singleton basato su Enum).

Dal momento che hai Effective Java, allora si dovrebbe già essere a conoscenza delle insidie ​​e problemi con Cloneable. Detto questo, se hai intenzione di implementare un singleton uno dei modi "sbagliati", no, non c'è assolutamente alcun motivo per implementare Cloneable e sovrascrivere Object#clone() solo per lanciare CloneNotSupportedException. Object#clone() fa già questo quando l'interfaccia Cloneable è assente.

+1

+1 - E compri l'eccellente [efficace Java] di Josh Bloch (http://java.sun.com/docs/books/effective/) che copre questo e altro. –

+0

Sì, lo so e ho il libro. Ma la mia domanda riguarda il consiglio di clonazione dato in tali articoli. Ci sono casi in cui questo consiglio ha senso? – shrini1000

+0

Dato che non è possibile clonare un 'enum', no. –

2

Vedere https://stackoverflow.com/a/71399/385478 per il modo più sicuro per applicare il modello Singleton. In sostanza, rendere Singleton un enum piuttosto che uno class, con un singolo valore INSTANCE.

2

Quando si scrive una classe utilizzando il modello Singleton, solo una istanza di classe può esistere alla volta. Di conseguenza, la classe non deve essere autorizzata a creare un clone.

Il modello singleton dice che esiste solo una istanza della classe all'interno del programma, quindi è giusto aumentare CloneNotSupportedException nel metodo Clone().

+1

Se si crea un singleton nel modo corretto in java usando un 'enum', questo non è un problema. –

+2

Wow, quale epoca in cui l'hacking di un singleton da un enum è considerato il modo giusto di fare le cose. – Perception

0

È necessario eseguire l'override del metodo clone() solo se la classe singleton implementa l'interfaccia Cloneable o una classe che implementa l'interfaccia Cloneable.

2

È necessario se la classe Singleton estende una classe che ha un metodo clone() visibile definito nella relativa gerarchia.

6

@ shrini1000, avete una domanda valida, ma la suggetsion circa clone è molto specifico per condizione seguente

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

Quanto sopra è necessario solo se la superclasse di una classe Singleton implementa un clone pubblico() metodo.

+1

Thx Gourabp; ma ho visto molti esempi in cui il Singleton non era una sottoclasse e tuttavia impediva esplicitamente la clonazione, da qui la mia domanda. – shrini1000

2

È possibile evitare la clonazione assegnando l'oggetto già creato con il metodo clone.

public Object clone() { 

return singletoneObject; 

} 
3

Il codice qui sotto è per prevenire la classe Singleton essere cloned.Override il metodo clone e gettare nuova 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

Per impostazione predefinita, il metodo clone() è contrassegnato come protetto, ma se SingletonObject estende un'altra classe che supporta la clonazione, è possibile violare i principi di progettazione del singleton. Quindi, per essere assolutamente sicuri al 100% che un singleton sia davvero un singleton, dobbiamo aggiungere un metodo clone() e lanciare un CloneNotSupportedException se qualcuno osa tentare! –

1

L'esempio migliore che ho trovato è questo:

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

Secondo la mia comprensione non è necessario implementare il metodo clone(). Motivo: 1. Se non si implementa il metodo clone e l'interfaccia Cloneable, verrà generata l'eccezione CloneNotSupportedException. 2. il metodo clone è protetto e non è possibile sottoclasse una classe singleton.

Problemi correlati