Le singleton

Sébastien MERIC

Classe dont on veut s'assurer qu'il n'existera qu'une et une seule instance dans l'espace et dans le temps d'un bout à l'autre du cycle de vie de l'application.

Ce document présente le singleton, un design pattern très connu, et si facile à appréhender qu'il est souvent trop utilisé.

- Titre : Le singleton

- Auteur : Sébastien MERIC

- Parution : 17 février 2003

- Mise à jour : 19 juin 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Sébastien MERIC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Synonymes

- II. Synopsis

- III. Structure

- IV. Implémentation

- V. Réflexion sur l'unicité de l'instance

I - Synonymes

Le nom du design pattern est essentiel. En effet, quand on utilise des normes afin d'être lisible par le plus grand nombre, afin d'être communicatif, il est primordial de pouvoir nommer l'outil que l'on utilise, et il est important que la terminologie soit partagée par tous. Voici donc pourquoi bien que le nom que je donne au pattern soit celui généralement partagé, il peut néanmoins apparaître d'autres nominations qu'il est bon d'exposer. Pour le singleton, il n'existe pas vraiment d'autres dénominations, mais vous entendrez peut-être parler de class à instance unique pour le désigner.

II - Synopsis

Le singleton permet de s'assurer qu'une seule instance d'un objet donné sera instanciée pendant toute la durée de votre application. Une seule dans l'espace comme dans le temps, c'est-à-dire :

l'espace représenté par la mémoire - vous êtes certain de l'unicité de l'instance à un moment donné

le temps - vous vous assurer de l'unicité de l'instance à chaque appel. J'entends par la que vous êtes certain que c'est la même instance que vous référer quel que soit le temps écoulé entre deux appels.

III - Structure

Pour s'assurer de l'unicité de l'instance de cette classe, il faut, pour commencer, penser à mettre les constructeurs de la classe en accessibilité limitée : privée ou tout au moins protégée (attention toutefois, le constructeur protégé ne permet de s'assurer de l'unicité de l'instance et de ses héritières ! ).

Pour permettre d'accéder à cette instance unique, il est également nécessaire de penser à fournir un point d'appel, on fournira donc une méthode statique. Un standard ne de nommage existant, nous l'utilisons donc et appelons la méthode : getInstance().

IV - Implémentation

Voici donc l'implémentation en Java :

/** Exemple d'implémentation d'un singleton.<p>
* Cet exemple ne fait rien.
*/

public class Singleton {

/** Récupère l'instance unique de la class Singleton.<p>
* Remarque : le constructeur est rendu inaccessible
*/
publicstatic Singleton getInstance() {
if (null == instance) { // Premier appel
instance = new Singleton();
}
return instance;
}

/** Constructeur redéfini comme étant privé pour interdire
* son appel et forcer à passer par la méthode <link
*/
private Singleton() {
}

/** L'instance statique */
private static Singleton instance;
}

V - Réflexion sur l'unicité de l'instance

Bien qu'il puisse apparaître à la lecture de ce pattern que l'instance est bien unique et ne peut pas être dupliquée, il existe un cas de figure où l'affirmation est fausse : le multithreading.

En effet, dans le cas de multithreading, l'instance présentée sous cette forme sera multiple si deux threads essayent d'accéder ensemble à la méthode getInstance().

La parade pourrait alors être (je suis ouvert à d'autres propositions bien entendu) :

/** Exemple d'implémentation d'un singleton dans le cas du multithreading.<p>
* Cet exemple ne fait rien.
*/

public class Singleton {

/** Récupère l'instance unique de la class Singleton.<p>
* Remarque : le constructeur est rendu inaccessible
*/
public static Singleton getInstance() {
if (null == instance) { // Premier appel
synchronized(objetSynchrone__) {
if (null == instance) {
instance = new Singleton();
}
}
}
return instance;
}

/** Constructeur redéfini comme étant privé pour interdire
* son appel et forcer à passer par la méthode <link
*/
private Singleton() {
}

/** L'instance statique */
private static Singleton instance;
/** objet pour la synchronisation. <p>
* j'ajoute deux "soulignés" (__) au nom de l'attribut car il n'a
* qu'un intérêt purement technique.
*/
private static Object objetSynchrone__;
}