Singleton

La programmation avec design patterns

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
Parfois avoir un seul exemplaire est mieux qu'en avoir plusieurs. Le développement des applications ne fait pas l'exception à cette règle et l'introduit dans le monde des design patterns avec singleton.

Singleton est le patron de conception appartenant à la famille des patrons créationnels. Son objectif est de s'assurer qu'une seule instance est utilisée par les classes. Il peut le faire grâce à l'application de la technique just-in-time initialization (initialisation en temps). Cela veut dire que tant que l'instance n'est pas demandée, tant elle n'existe pas. Cependant, l'initialisation avant est aussi possible mais elle est déconseillée.

Ce patron de conception est composé d'une seule classe. Il s'agit de la classe dont l'instance devra être unique à travers toute l'application. Cette unicité doit être achevé par la non-initialisation de cette classe. On peut en déduire que la méthode permettant de retourner l'instance sera une méthode statique et publique.

Pour certains lanages qui sont multi-threading, comme Java, la mise en place du singleton est un peu plus compliquée. En fait il faut s'assurer que tous les threads utiliseront la même instance. Trois solutions s'imposent pour Java :
- la synchronisation à l'aide du block synchronized, comme ci-dessous :

synchronized(SingletonExample.class) {
if (singleton == null) {
singleton = new SingletonExample();
}
}
return singleton;

- l'utilisation du mot-clé volatile :

private volatile static SingletonExample singleton;

- l'utilisation des énumérations qui, par définition, sont thread-safe :

public enum SingletonExample {
SINGLETON;
public void invokeSingletonAction() {
// do something with SINGLETON instance
}
};


Exemple du singleton
Pour mieux comprendre le singleton, on utilisera l'exemple d'une famille complète, composée d'un père et d'une mère. Il est impossible biologiquement, qu'un enfant en ait plusieurs. C'est pourquoi on utilisera le singleton pour les représenter.

class Father {
private String name;
private static Father father;

public Father(String name) {
this.name = name;
}

public static Father getFather() {
if (father == null) father = new Father("Good father");
return father;
}

@Override
public String toString() {
return "Father "+this.name;
}
}

class Mother {

private String name;
private static Mother mother;


public Mother(String name) {
this.name = name;
}

public static Mother getMother() {
if (mother == null) mother = new Mother("Good mother");
return mother;
}

@Override
public String toString() {
return "Mother "+this.name;
}
}

Ce code représente le singleton. On remarque que les getters pour les attributs sont bien publiques. La présence de l'initialisation en temps est également implémentée. Cet exemple montre que singleton peut


Father father1 = Father.getFather();
Father father2 = Father.getFather();
Mother mother1 = Mother.getMother();
Mother mother2 = Mother.getMother();
System.out.println("Mother of happy family : " + mother1);
System.out.println("Mother of happy family : " + mother2);
System.out.println("Father of happy family : " + father1);
System.out.println("Father of happy family : " + father2);



Mother of happy family : Mother Good mother
Mother of happy family : Mother Good mother
Father of happy family : Father Good father
Father of happy family : Father Good father

Le code du client, présenté ci-dessus, illustre bien qu'on travaille uniquement sur une seule instance de chaque classe.

Le design pattern présenté dans cet article est donc très utile dans des situations où une seule instance d'une classe est obligatoire. Néanmoins, il faut éviter des pièges liés à des langanges supportant le multi-threading, comme Java.
Bartosz KONIECZNY 09-03-2014 16:48 design patterns
Un conseil Android

Comment accéder au localhost ?

A la place de 127.0.0.1 il faut utiliser 10.0.2.2.