web-dev-qa-db-fra.com

Singleton design pattern et prévention du clonage

De nombreux articles que j'ai lus sur le Net à propos du modèle de conception Singleton mentionnent que la classe devrait surcharger la méthode 'clone ()' et qu'elle renverrait une exception 'CloneNotSupported'. Est-ce vraiment nécessaire?

Par défaut, la méthode clone () est protégée, de sorte qu'aucune classe (à l'exception de celles du même package) ne puisse l'appeler sur cette instance Singleton. De plus, si ce Singleton n’implémente pas Cloneable, même si cette méthode est appelée, elle générera une exception d’exécution. De plus, le constructeur étant privé, nous ne pourrons pas le sous-classer et ainsi permettre son clonage. Donc, devrais-je toujours mettre en œuvre ce conseil pour mes cours Singleton?

EDIT: Juste pour clarifier: je ne cherche pas la meilleure façon possible de mettre en œuvre Singleton. Je demande simplement à propos de la validité des conseils mentionnés ci-dessus, avec le modèle Singleton «normal» (et non pas Singleton basé sur Enum).

23
shrini1000

Si vous voulez vraiment implémenter un singleton, utilisez une énumération à un élément et arrêtez d'y penser.


EDIT: Juste pour clarifier: je ne cherche pas la meilleure façon possible de mettre en œuvre Singleton. Je demande simplement à propos de la validité des conseils mentionnés ci-dessus, avec le modèle Singleton «normal» (et non pas Singleton basé sur Enum).

Puisque vous avez Effective Java,}, vous devriez déjà être au courant des pièges et des problèmes liés à Cloneable. Cela dit, si vous voulez implémenter un singleton d’une des "mauvaises" façons, non, il n’ya absolument aucune raison de mettre en oeuvre Cloneable et de remplacer Object#clone() simplement pour lancer CloneNotSupportedException. Object#clone() le fait déjà lorsque l'interface Cloneable est absente.

24
Matt Ball

@ shrini1000, Vous avez une question valide, mais la suggestion concernant le clone est très spécifique à la condition suivante

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

Ce qui précède n'est nécessaire que si une superclasse d'une classe singleton implémente une méthode public clone () .

7
Gourabp

Le code ci-dessous est destiné à empêcher le clonage de la classe singleton.Override la méthode clone et lance la nouvelle 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
Rahul Tripathi

Cela est nécessaire si votre classe Singleton étend une classe ayant une méthode visible clone () définie dans sa hiérarchie.

2
user2103311

Vous pouvez éviter le clonage en donnant à l'objet déjà créé par la méthode de clonage.

public Object clone() {

return singletoneObject;

}
2
user3020398

Voir https://stackoverflow.com/a/71399/385478 pour le moyen le plus sûr d'appliquer le modèle Singleton. Faites essentiellement de votre Singleton une enum plutôt qu'une class, avec une seule valeur INSTANCE.

2
Graham Borland

Lors de l'écriture d'une classe en utilisant le modèle Singleton, une seule instance de cette classe peut exister à la fois. En conséquence, la classe ne doit pas être autorisé à faire un clone.

Le modèle singleton indique qu'une seule instance de la classe existe dans le programme. Il est donc correct de créer une exception CloneNotSupportedException dans la méthode Clone ().

2
aleroot

Le meilleur exemple que j'ai trouvé est celui-ci:

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
1
hitesh141

D'après ma compréhension, il n'est pas nécessaire d'implémenter la méthode clone (). Raison: 1. Si vous n'implémentez pas la méthode clone et l'interface Cloneable, une exception CloneNotSupportedException . La méthode clone est protégée et vous ne pouvez pas sous-classer une classe singleton.

0
Anirban B

Vous devez redéfinir la méthode clone() uniquement si votre classe singleton implémente l'interface Cloneable ou une classe implémentant l'interface Cloneable.

0
prageeth