Publié le 07/17/2017, rédigé par Ernest RIBEIRO

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 :

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).

Diagramme de classes Singleton synchronized

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'
    }
}