2012-02-16 23 views
19

Muchos artículos que he leído en la Red sobre el patrón de diseño Singleton mencionan que la clase debe anular el método 'clone()' y en él, lanzar la excepción 'CloneNotSupported'. ¿Es esto realmente necesario?Patrón de diseño Singleton y prevención de clonación

El método clone() está protegido por defecto, por lo que ninguna clase (excepto las del mismo paquete) podría llamarlo en esa instancia de Singleton. Además, si este Singleton no implementa Cloneable, incluso si se llama a este método, dará una excepción de tiempo de ejecución. Además, como el constructor es privado, no podremos subclasificarlo y así permitir su clonación. Entonces, ¿debería implementar este consejo para mis clases de Singleton?

EDIT: Para aclarar: no estoy buscando la mejor manera de implementar Singleton. Solo estoy preguntando sobre la validez del consejo mencionado anteriormente, es decir, sobre el patrón Singleton "normal" (y no sobre el singleton Enum).

+2

Estás preguntando "Si estoy creando conjuntos unitarios de manera equivocada, que no debería hacer, en caso de Estoy preocupado por X ". La respuesta es hacerlo de la manera correcta que hace que su pregunta sea discutible. No, no tienes que preocuparte por esto. –

Respuesta

18

Si realmente va a implementar un singleton, use a one-element enum y deje de pensar en ello.


EDIT: Solo para aclarar: No estoy en busca de la mejor manera posible implementar Singleton. Solo estoy preguntando sobre la validez del consejo mencionado anteriormente, es decir, sobre el patrón Singleton "normal" (y no sobre el singleton Enum).

Puesto que usted tiene Effective Java, entonces ya debería estar conscientes de las dificultades y problemas con Cloneable. Dicho esto, si va a implementar un singleton de las formas "incorrectas", no, no hay absolutamente ninguna razón para implementar Cloneable y anular Object#clone() solo para arrojar CloneNotSupportedException. Object#clone() ya lo hace cuando la interfaz Cloneable está ausente.

+1

+1 - Y compre la excelente [Java efectiva] de Josh Bloch (http://java.sun.com/docs/books/effective/) que cubre eso y más. –

+0

Sí, lo sé y tengo el libro. Pero mi pregunta es sobre los consejos de clonación dados en tales artículos. ¿Hay algún caso donde este consejo tenga sentido? – shrini1000

+0

Como no puedes clonar un 'enum', no. –

2

Consulte https://stackoverflow.com/a/71399/385478 para ver la forma más segura de aplicar el patrón de Singleton. Básicamente, haga de su Singleton un enum en lugar de un class, con un valor único de INSTANCE.

2

Al escribir una clase con el patrón Singleton, solo una instancia de puede existir a la vez. Como resultado, la clase no debe ser permitida para hacer un clon.

El patrón singleton dice que solo existe una instancia de la clase dentro del programa, por lo que es correcto generar CloneNotSupportedException en el método Clone().

+1

Si crea un singleton de la manera correcta en java usando un 'enum', esto no es un problema. –

+2

Guau, qué edad cuando piratear un singleton de una enumeración se considera la manera correcta de hacer las cosas. – Perception

0

Debe sobrescribir el método clone() solo si su clase singleton implementa la interfaz Cloneable o una clase que implementa la interfaz Cloneable.

2

Es necesario si su clase Singleton amplía una clase que tiene un método clone() visible definido en su jerarquía.

6

@ shrini1000, usted tiene una pregunta válida, pero el suggetsion sobre clon es muy específico a condición siguiente

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

Lo anterior sólo es necesario si una superclase de una clase Singleton implementa un clon pública() método.

+1

Thx Gourabp; pero he visto muchos ejemplos en los que el Singleton no era una subclase y, sin embargo, impedía explícitamente la clonación, de ahí mi pregunta. – shrini1000

2

Puede evitar la clonación dando un objeto ya creado por método de clonación.

public Object clone() { 

return singletoneObject; 

} 
3

El código siguiente es para la prevención de la clase singleton ser cloned.Override el método de clon y arrojar nueva 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

De forma predeterminada, el método clone() está marcado como protegido, pero si su SingletonObject amplía otra clase que no admite clonación, es posible violar los principios de diseño del singleton. Entonces, para estar absolutamente 100% seguros de que un singleton realmente es singleton, debemos agregar un método clone() y lanzar una CloneNotSupportedException si alguien se atreve a intentarlo. –

1

El mejor ejemplo que he encontrado es esto:

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

Según mi entender, no es necesario implementar el método clone(). Motivo: 1. Si no implementa el método de clonación y la interfaz clonable, lanzará CloneNotSupportedException. 2. El método de clonación está protegido y no puede subclasificar una clase singleton.