Pattern Singleton
Implémentation du pattern en Java Singleton (avec Lazy-Loading)
Attention : cet article est une des implémentations possibles du design pattern Singleton en Java. Cette implémentation est un peu plus compliquée à mettre en oeuvre mais fournie les meilleures performances.
La liste des implémentations possibles en Java est accessible en bas de cette page.
Caractéristiques de cette implémenation :
- [
OK ] Une seule et unique instance pour toute l'application. - [
OK ] Gestion des accès multi-threads. - [
OK ] Instanciations extérieures impossibles. - [
OK ] Chargement / Récupération rapide de l'instance. - [
OK ] Instanciation seulement à la première invocation.
Diagramme de classes
Ce diagramme ajoute une classe interne et private à notre singleton, ce qui lui permet l'instanciation à la première demande et non au chargement de la JVM (même si la classe n'était jamais utilisée).
Implémentation
public class MySingleton {
/**
* Les classes internes ne sont évaluées qu'à l'exécution en Java d'où
* l'aspect Lazy-Loading de cette implémentation.
*/
private static class MySingletonLoader {
/**
* L'instance est 'static' afin d'être unique.
* L'instance est 'final' afin de ne jamais être réinstanciée.
*
* Le singleton est instancié à l'évaluation de la classe interne
* par la JVM qui gérera les accès concurrents à ce moment-là.
*/
private static final MySingleton INSTANCE = new MySingleton();
}
/**
* Le constructeur est privé afin d'éviter que d'autres classes puissent
* créer une autre instance.
*/
private MySingleton() {
}
/**
* Cette méthode n'a plus besoin d'être 'synchronized', les performances à
* la récupération seront maximales.
*/
public static MySingleton getInstance() {
// Ici, il faut accéder à l'instance du Singleton en passant par le loader.
return MySingletonLoader.INSTANCE;
}
// Exemple d'utilisation
public static void main(String... args) {
MySingleton a, b;
a = MySingleton.getInstance(); // L'instance est créée.
b = MySingleton.getInstance(); // La première instance est retournée
System.out.println(a == b); // Références identiques => affiche 'true'
}
}