IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Design Pattern : les mémentos

Image non disponible

Un design pattern décrit une solution standard, utilisable dans la conception de logiciels, à des questions classiques et récurrentes.

Cet article vous redonne les points clés pour utiliser les patterns les plus utiles. Il vous propose surtout de télécharger des mémentos à imprimer au bureau.

Pour le moment, il n'y a que le mémento pour le Singleton mais d'autres mémentos viendront prochainement. 9 commentaires Donner une note à l´article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Un design pattern décrit une solution standard, utilisable dans la conception de logiciels, à des questions classiques et récurrentes.

Les patrons de conception les plus connus sont au nombre de vingt-trois : Abstract factory, Builder, Factory, Prototype, Singleton, Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy, Memento, Strategy, Command, Chain of responsability, Interpreter, Iterator, Mediator, Template, Visitor, State et Observer. On les classe généralement en trois familles : Création, Structure et Comportement. Ils sont désignés sous le nom de « Gang of Four » (GOF) en référence aux quatre créateurs du concept.

Cet article vous redonne les points clés pour bien comprendre/utiliser les patterns les plus utiles. Il vous propose surtout de télécharger des mémentos à imprimer vous-même au bureau.

Le mémento vous est offert sous licence « Creative Commons CC BY-NC-SA 3.0 FR ». Vous êtes libre de partager (reproduire, distribuer et communiquer) cette œuvre. Ce n'est pas de la publicité. C'est un cadeau pour lequel je ne demande aucune contrepartie. Toutefois, si vous appréciez ce mémento et si vous l'utilisez/distribuez, ça nous fera plaisir de le savoir. Consultez les FAQ pour en savoir plus.

I-A. Patterns par ordre alphabétique

Voici tous les patterns de cet article, classés par ordre alphabétique :

I-B. Patterns par famille

Patterns de création :

Patterns de structure :

  • bientôt

Patterns de comportement :

  • bientôt

I-C. Mises à jour

La première version de ce document a été écrite avec un seul pattern : le singleton. D'autres patterns (et les mémentos associés) seront ajoutés au fur et à mesure.

29 janvier 2014 : création du document (avec seulement le Singleton)

II. Design patterns

 

II-A. Singleton

II-A-1. Principe

Le singleton permet de s'assurer qu'il n'existe qu'une seule instance d'une classe dans un environnement et pour une durée d'exécution donnés.

Points clés :

  • instance privée et statique ;
  • constructeur privé ;
  • méthode d'accès publique et statique.
Image non disponible
Diagramme de classe du Singleton
Version classique
Sélectionnez
public class DogService {
    private static DogService instance;

    private DogService() {
        ...
    }

    public static DogService getInstance() {
        if (instance == null) {
            instance = new DogService();
        }
        return instance;
    }

    public void truc() {
        ...
    }

    ...
}
Utilisation
Sélectionnez
DogService dogService = DogService.getInstance();

dogService.truc();

II-A-2. Synchronisation

Dans un contexte multithread, l'utilisation du pattern Singleton nécessite des précautions pour limiter les problèmes d'accès concurrents. Il faut synchroniser les appels et les initialisations.

Synchro simple
Sélectionnez
public static synchronized DogService getInstance() {
    if (instance == null) {
        instance = new DogService();
    }
    return instance;
}

Malheureusement, on paie le coût de la synchronisation, réalisée grâce au mot-clé « synchronized », à chaque appel et non pas seulement au premier (i.e. initialisation).

Des variantes (plus ou moins efficaces) permettent d'assurer la synchronisation ; vous en retrouverez une sélection ci-dessous. Je vous recommande également/vivement de consulter l'article de Christophe Jollivet intitulé « Le Singleton en environnement Multithread » dont je me suis allègrement inspiré pour écrire cet article.

II-A-2-a. Double-checked locking
Double-checked locking
Sélectionnez
public static DogService getInstance() {
    if (instance == null) {
        synchronized (DogService.class) {
            if (instance == null) {
                instance = new DogService();
            }
        }
    }
    return instance;
}

La théorie semble parfaite et de nombreux sites Web recommandent cette solution. Le DCL n'apporte pourtant aucune garantie que cela fonctionnera. Ceci n'est pas inhérent à un bogue de la JVM mais au modèle de mémoire qui autorise l'écriture dans le désordre (« out-of-order writes »).

II-A-2-b. Mot-clé volatile
Mot-clé volatile
Sélectionnez
private static volatile DogService instance;

Là encore, c'est une « fausse bonne idée ». Dans les anciennes JVM, ça n'offre pas de garantie. Cela fonctionne dans les nouvelles versions, mais provoque un flush complet du registre du processeur. Le gain de performance recherché en n'utilisant pas la synchronisation est alors nul.

II-A-2-c. Thread local
Thread local
Sélectionnez
public class DogService {
    private static final ThreadLocal tl = new ThreadLocal();
    private static DogService instance;

    private DogService() { 
        ...
    }

    public static DogService getInstance() {
        if (tl.get() == null) {
            synchronized (DogService.class) {
                if (instance == null) {
                    instance = new DogService();
                }
                tl.set(Boolean.TRUE);
            }
        }
        return instance;
    }
}

Défaut : l'utilisation du thread local est un peu lente.

II-A-2-d. Initialisation statique
Initialisation statique
Sélectionnez
private static final DogService instance = new DogService();

L'initialisation est faite au lancement, même si le service n'est finalement jamais utilisé.

II-A-2-e. Inner class
Inner class
Sélectionnez
public class DogService {
    private static class InstanceHolder {
        public static final DogService instance    = new DogService();
    }

    private DogService() { 
        ... 
    }

    public static DogService getInstance() {
        return InstanceHolder.instance;
    }
}

Le chargement des classes est « thread-safe » ; la classe encapsulée n'est initialisée que lors de l'appel de la méthode.

II-A-2-f. Enum
Enum
Sélectionnez
public enum DogService {
    INSTANCE;

    public static DogService getInstance() {
        return INSTANCE;
    }
}
Utilisation
Sélectionnez
final DogService service = DogService.getInstance();

// ou comme un enum
final DogService service = DogService.INSTANCE;

L'emploi d'un enum permet de prendre en compte le cas de la sérialisation facilement et empêche complètement l'initialisation par réflexion.

II-A-3. JSR330

Des frameworks d'injection (CDI, Spring, Guice, etc.) savent initialiser une variable comme un singleton.

@Singleton
Sélectionnez
@Singleton
public class DogService {
    ...
}
Injection
Sélectionnez
public class UneClasse {
    @Inject
    private DogService service;
        ...
    }

    ...

Dans une application professionnelle, il est fort probable que vous utiliserez une bibliothèque comme Spring dont le Singleton est le « scope » par défaut. Avec ce type de framework, on n'a pas besoin (et on ne doit pas) programmer soi-même le Singleton.

II-A-4. Mémento

Téléchargez gratuitement le fichier « memento_singleton.pdf » (461 Ko) pour l'imprimer au bureau.

Image non disponible
Image non disponible
Mémento sur le Singleton face 1
Image non disponible
Mémento sur le Singleton face 2

III. Tous les mémentos

Image non disponible
memento_singleton.pdf
   
     

IV. Conclusion

Et voilà... Revenez de temps en temps pour découvrir les nouveaux mémentos qui seront ajoutés.

Vos retours nous aident à améliorer nos publications. N'hésitez donc pas à commenter cet article sur le forum : 9 commentaires Donner une note à l´article (5)

V. Remerciements

J'adresse de grands remerciements aux personnes qui ont contribué à l'écriture de cet article ainsi qu'aux mémentos associés, en particulier à Mickael BARON, Julien, Logan, Michel Dirix, Nicolas et Philippe DUVAL.

VI. Annexes

VI-A. Liens

Retrouvez quelques design pattern sur Developpez.com :
https://smeric.developpez.com/java/uml/

Article de Christophe Jollivet, intitulé « Le Singleton en environnement Multithread » :
https://christophej.developpez.com/tutoriel/java/singleton/multithread/

VI-B. Liens perso

VI-C. FAQ

VI-C-1. Comment imprimer les mémentos au bureau ?

Les mémentos doivent être imprimés sur du papier au format A4 avec une orientation paysage. Cela est déjà configuré dans les fichiers PDF, mais je vous conseille de vérifier que le pilote de votre imprimante le respecte.

La plupart des imprimantes vont essayer de mettre le document à l'échelle, car les fichiers PDF des mémentos sont conçus pour rogner les marges au maximum. Dans la fenêtre des options d'impression, il faudra donc désactiver la mise à l'échelle. En général, il suffit de cocher (ou de décocher selon que c'est une négation ou une option) la mise à l'échelle.

Image non disponible

Il faudra aussi demander une impression recto verso sur bord court. Le réglage par défaut est généralement d'imprimer sur bord long, ce qui convient aux documents à orientation en portrait, mais pas aux mémentos, qui sont orientés en paysage.

Image non disponible

VI-C-2. Comment plier les mémentos imprimés ?

Les mémentos sont constitués de trois volets qu'il va falloir plier. Il existe deux façons de plier un document constitué de trois volets : en zigzag ou en enroulé.

Image non disponible
pliage en zigzag ou enroulé

Pour les mémentos offerts sur cette page, il convient de faire un pliage enroulé (ou fermé). Une fois plié, le volet 3 se retrouve à l'intérieur.

Image non disponible

Il y a une petite ligne en pointillé en bas du verso.

Image non disponible
Ligne pointillée

Il faut replier le premier volet du mémento sur cette ligne, ce qui créera le premier pli (entre les volets 1 et 2).

Si vous être droitier, je vous conseille de tenir le mémento à l'envers, de sorte que la petite ligne en pointillé soit en haut. Pour pourrez ainsi utiliser votre main droite pour replier le premier volet. Remettez ensuite le document à l'endroit pour faire le second pli.

Image non disponible

Pour obtenir le second pli (entre les volets 2 et 3), il suffit de replier le morceau restant à l'intérieur en se servant du premier pli comme butée. Le second pli devrait alors se faire au niveau de la petite ligne en pointillé.

Image non disponible

VI-C-3. Que permet la licence CC BY-NC-SA 3.0 FR ?

La licence Creative Commons vous demande de respecter trois points : attribution, pas d'utilisation commerciale et pas d'œuvre dérivée. Si vous souhaitez modifier ce mémento, par exemple pour l'utiliser dans une de vos plaquettes ou pour ajouter votre logo, il vous suffit de me contacter et j'aurai le plaisir de vous accompagner et de vous offrir (gratuitement) une version utilisable et plus pratique.

VI-C-4. Peut-on commander des mémentos déjà imprimés et pliés ?

Oui c'est possible. Notre objectif n'est pas de gagner de l'argent grâce aux mémentos. Nous les rédigeons, car notre passion est le développement et que nous souhaitons la partager et la rendre simple. Nous pouvons imprimer les mémentos sur du papier épais, les plier et vous les envoyer. Dans ce cas, nous vous demanderons juste une petite participation aux frais d'envoi.

VI-C-5. Peut-on redistribuer les mémentos ?

La réponse la plus simple serait de dire « oui ». Toutefois, au lieu de distribuer vous-même les mémentos, je vous invite à donner l'adresse de ce document. Les visiteurs pourront ainsi profiter des prochaines mises à jour.

VI-C-6. Comment peut-on vous soutenir ?

Le mieux est de parler de nous en donnant l'adresse de cette page à vos contacts. Nous avons également toujours besoin de sponsors qui nous permettraient, par exemple, de consacrer plus de temps à la création et à l'amélioration de contenus de qualité.

Nous avons également besoin de vos retours. Ils nous aident à améliorer nos publications. Nous sommes preneurs des critiques positives et négatives, des remarques et des bonnes idées.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

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 Thierry Leriche-Dessirier. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.