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

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Apprendre à coder le patron de conception Singleton en Java,
Un tutoriel de François-Xavier Robin

Le , par Mickael Baron

57PARTAGES

13  0 
Bonjour,

François-Xavier Robin nous propose un tutoriel pour apprendre à coder le patron de conception Singleton en Java.

Pour consulter le tutoriel : https://fxrobin.developpez.com/tutor...on-conception/

N'hésitez pas à laisser des commentaires à la suite.

Mickael BARON pour l'équipe Java de Developpez.com

Retrouver les meilleurs cours et tutoriels pour apprendre la programmation en Java

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de sekaijin
Expert éminent https://www.developpez.com
Le 10/11/2018 à 16:12
Merci pour cet article qui a le mérite d'être clair

Mais il y a un gros manque cet article fait l'impasse des JSE dans lequel on a de multiples classloader
Il explique clairement que le singleton est lié au classLoader mais il n'est pas explicitement dit que si on a deux classLoader on a potentiellement deux instances.

Le plus simple pour s'en convaincre est de faire 1 jar avec un singleton contenant une methode getVersion qui retourne la version. le compiler en version 1.0 puis en version 2.0

faire un autre jar qui importe la version 1.0 et qui appelle la dite méthode. recommencer avec une dépendance vers la version 2.0

déployez le tout dans un conteneur genre OSGI et le premier appel à getVersion renvoie 1.0 et le second envoie 2.0
on a donc deux fois le même singleton dans deux version différentes. (ce qui peut être le but recherché)

Mais si on fait dépendre le dernier jar de la version 1.0 et qu'on fait afficher la methode getMessage on va voir que les deux appels ne renvoient pas la même instance du même singleton dans la même version. on a alors un singleton qui est instancié deux fois.

cela est du au fait que chaque jar à son propre classLoader et que lorsqu'on importe une dépendance dans un jar on le fait avec son propre classLoader.

Comme dit dans l'article JEE n'est pas abordé car justement dans son cas il y a plusieurs ClassLoader et ce pattern ne permet pas l'unicité.

Je tenais à ajouter que avoir un JSE et ce pattern ne le garanti pas.
pour que ce pattern fonctionne correctement il faut un JSE et un unique ClasseLoader (ce qui est le cas 90% du temps).

Quant à l'aparté sur les Servlets le propos est a modérer aussi. le servelt est unique dans le war mais pas dans la plateforme.
si on l'utilise pour avoir un accès exclusif à une ressource ça ne fonctionne pas. car pour cela il faut que l'unicité soit au niveau de la plateforme JEE et non du war.
le même servlet présent dans deux war donnera deux instances donc plus d'exclusivité.

A+JYT
1  0 
Avatar de professeur shadoko
Membre chevronné https://www.developpez.com
Le 15/11/2018 à 17:06
j'en profite pour relancer une discussion plus générale: les singletons sont-ils souvent une mauvaise idée?
2 points:
- à mon pas très humble avis un programmeur "réalisant" (celui qui écrit le code que les autres programmeurs "clients" vont utiliser) aurait tout intérêt à encapsuler son singleton. Je veux dire que si lui sait qu'il existe une seule instance les programmeurs "clients" ne devraient pas le savoir. Intérêt de la démarche: on pourra toujours se rendre compte finalement qu'il n'y a pas qu'une seule instance et alors les codes "clients" ne seront pas à modifier.
- malheureusement on peut imposer abusivement le fait qu'il n'y ait qu'une seule instance de quelques chose. ça m'est arrivé d'être coincé par ce genre de contrainte ... Il me semble me souvenir (mais je n'en suis pas sûr) que c'est par exemple le problème du Logger système : les concepteurs sont partis du principe qu'il n'y avait qu'un seul système de logging pour l'ensemble d'une application... Cette unicité est-elle évidente ? je n'en suis pas si sûr (on peut arguer que la multiplicité serait une hérésie oui ... mais ...)
0  0 
Avatar de Pyramidev
Expert éminent https://www.developpez.com
Le 15/11/2018 à 20:30
Bonjour,

Citation Envoyé par professeur shadoko Voir le message
j'en profite pour relancer une discussion plus générale: les singletons sont-ils souvent une mauvaise idée?
Dans le code que je lis au quotidien (le plus souvent du C++), le singleton est plus souvent mal utilisé que bien utilisé.

Le plus gros problème, ce sont les dépendances implicites. Par exemple, quand on a une routine A qui appelle une routine B qui elle-même appelle une routine C, etc. qui appelle une routine F qui elle-même accède directement à un singleton MyGlobalDirtyConfig alors, quand on lit le code de la routine A, on ne voit pas que son comportement dépend de l'état de l'instance de la classe MyGlobalDirtyConfig.
Celui qui a introduit à l'arrache la classe MyGlobalDirtyConfig dans le code se rappelle qui dépend de quoi, donc ne sera pas très gêné par cette dépendance implicite quand il modifiera le code. Mais, de nombreuses années après, quand le code aura bien grossi, les malheureux qui récupèreront le projet et qui auront besoin de changer le code de la routine A sans avoir une vision omnisciente du programme risqueront de ne pas savoir que le comportement de A dépend de l'état de l'instance de la classe MyGlobalDirtyConfig. Du coup, des cas particuliers seront oubliés lors de la conception, du codage et des tests. Ensuite, une fois que le code partira en production et que l'instance de la classe MyGlobalDirtyConfig aura un état inhabituel : BOUM : comportement non prévu => anomalie => report de bogue du client => vite, il faut corriger, c'est urgent.

C'est pour ça que, le plus souvent, il faut éviter les variables globales muables et les singletons avec état. À la place, il faut transmettre de paramètre en paramètre ce dont les fonctions ont besoin. On peut voir cela comme une documentation des dépendances en partie vérifiée à la compilation : le comportement d'une fonction dépend de ce qu'on lui passe en paramètre.

Dans le cas particulier du logueur, un logueur singleton est moins grave, car ne pas avoir une vision claire de quel bout de code a besoin de loguer engendre rarement des bogues quand on modifie le code. Cela dit, je pense quand même qu'un logueur singleton est généralement une mauvaise idée.

Personnellement, quand je programme en objet, pour le logging, je crée une interface Logger qui n'offre qu'une seule méthode : la méthode qui sert à loguer et qui prend en paramètre un message et un niveau de log. La grande majorité du programme ne connaît que le type de base Logger. Les fonctions de haut niveau relaient aux fonctions de bas niveau un objet de type Logger (patron de conception Stratégie). Seule une petite partie du code connait les classes qui implémentent Logger.
Comme ça, la majorité du code est réutilisable avec le logueur qu'on veut : il suffit de passer en paramètre l'instance de la classe de log qu'on veut (mais qui doit implémenter l'interface Logger). On peut même facilement avoir une routine qui logue à un endroit et une autre qui logue à un autre endroit : il suffit de leur passer des logueurs différents en paramètre.

Cela dit, il y a quand même un cas particulier de logueur singleton que je trouve légitime : une classe NullLogger qui implémente Logger et qui ne logue rien (patron de conception Objet nul). Concrètement, cette classe sert donc à désactiver les écritures de logs, ce qui est souvent souhaitable pour les tests unitaires. Comme cette classe n'a pas d'état, il n'y a pas de raison de s'interdire d'en faire un singleton.

Edit 21h46 : reformulation : utilisation du terme "interface" au lieu de "classe de base abstraite" pour mieux coller au vocabulaire de Java.
0  0