Question

Le modèle singleton est un membre entièrement payé du rel = "noreferrer"> carnet de modèles , mais il semble que ce soit plutôt orphelin de nos jours. J'utilise toujours beaucoup de singletons, en particulier pour les classes d'usine , et vous devez être un Un peu prudent sur les problèmes de multithreading (comme toute classe en fait), je ne vois pas pourquoi ils sont si horribles.

Stack Overflow semble en particulier supposer que tout le monde convient que les singletons sont diaboliques. Pourquoi?

Veuillez appuyer vos réponses par des " faits, des références ou des compétences spécifiques" "

.
Était-ce utile?

La solution

Paraphrasé dans Brian Button:

  1. Ils sont généralement utilisés comme une instance globale, pourquoi est-ce si grave? Parce que vous masquez les dépendances de votre application dans votre code, au lieu de les exposer via les interfaces. Rendre une odeur de code quelque chose de global pour éviter de le laisser passer.

  2. Ils violent le principe de responsabilité unique : en raison du fait qu'ils contrôlent leur propre création et leur propre cycle de vie.

  3. Ils causent intrinsèquement un code étroitement lié au couplé . Cela rend souvent difficile de les simuler à l’essai.

  4. Ils transportent l'état pendant toute la durée de vie de l'application. Les tests sont un autre succès, car vous pouvez vous retrouver avec une situation dans laquelle des tests doivent être commandés, ce qui est un gros non pour les tests unitaires. Pourquoi? Parce que chaque test unitaire doit être indépendant de l'autre.

Autres conseils

Les singletons résolvent un (et un seul) problème.

Conflit de ressources.

Si vous avez une ressource qui

( 1 ) ne peut avoir qu'une seule instance et

( 2 ), vous devez gérer cette instance unique,

vous avez besoin d'un singleton .

Il n'y a pas beaucoup d'exemples. Un fichier de log est le gros. Vous ne voulez pas simplement abandonner un seul fichier journal. Vous voulez vider, synchroniser et fermer correctement. Ceci est un exemple de ressource partagée unique devant être gérée.

Il est rare que vous ayez besoin d'un singleton. La raison pour laquelle ils sont mauvais, c'est qu'ils se sentent comme un mondial et qu'ils sont entièrement payés membre du livre GoF Patterns Design .

Lorsque vous pensez avoir besoin d'un global, vous commettez probablement une terrible erreur de conception.

Certains snobs de code les considèrent comme un global glorifié. De la même manière que beaucoup de gens détestent la déclaration goto , il en existe d’autres qui détestent l’idée d’utiliser un global . J'ai vu plusieurs développeurs faire des efforts extraordinaires pour éviter un global , car ils considéraient en utiliser un comme un aveu d'échec. Étrange mais vrai.

En pratique, le modèle Singleton n’est qu’une technique de programmation utile dans votre boîte à outils. De temps en temps, vous pourriez trouver la solution idéale et vous en servir. Mais l’utiliser simplement pour pouvoir vous vanter d’utiliser un motif de conception est aussi stupide que de ne jamais l’utiliser, car c’est juste un global .

Misko Hevery, de Google, a publié des articles intéressants sur ce sujet ...

Les singletons sont des menteurs pathologiques a une unité Cet exemple de test illustre bien comment des singletons peuvent rendre difficile l'identification des chaînes de dépendance et le démarrage ou le test d'une application. C'est un exemple assez extrême d'abus, mais l'argument qu'il avance est toujours valable:

  

Les singletons ne sont rien d’autre qu’un état global. L’état global permet à vos objets de s’emparer secrètement de choses qui ne sont pas déclarées dans leurs API. Par conséquent, les singletons transforment vos API en menteurs pathologiques.

Où sont passés tous les singletons partis fait remarquer que l’injection de dépendance a facilité la transmission d’instances aux constructeurs qui en ont besoin, ce qui atténue la nécessité sous-jacente des mauvais Singletons globaux décriés dans le premier article.

Je pense que la confusion est causée par le fait que les gens ne connaissent pas la véritable application du modèle Singleton. Je ne saurais trop insister là-dessus. Singleton n'est pas un modèle à utiliser pour boucler les globaux. Le modèle Singleton ne doit être utilisé que pour garantir l’existence de une et une seule instance d’une classe pendant son exécution.

Les gens pensent que Singleton est diabolique parce qu’ils l’utilisent pour des globals. C'est à cause de cette confusion que Singleton est méprisé. S'il vous plaît, ne confondez pas Singletons et globals. Si utilisé aux fins pour lesquelles il était destiné, vous obtiendrez des avantages extrêmes du modèle Singleton.

Une des choses plutôt négatives sur les singletons est que vous ne pouvez pas les étendre très facilement. En gros, vous devez intégrer une sorte de modèle de décorateur ou quelque chose du genre si vous voulez changer leur comportement. En outre, si vous souhaitez disposer de plusieurs façons de procéder, il peut être assez pénible de changer, en fonction de la présentation de votre code.

Une chose à noter, si vous utilisez des singletons, essayez de les transmettre à ceux qui en ont besoin plutôt que de leur demander d'y accéder directement ... Sinon, si vous choisissez d'avoir plusieurs façons de faire ce que singleton fait, il sera assez difficile de changer car chaque classe intègre une dépendance si elle accède directement au singleton.

Donc en gros:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

plutôt que:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

Je crois que ce type de modèle s'appelle injection de dépendance et est généralement considéré comme une bonne chose.

Comme n'importe quel modèle cependant ... Réfléchissez-y et déterminez si son utilisation dans une situation donnée est inappropriée ou non ... Les règles sont généralement faites pour être enfreintes et modèles ne devrait pas être appliqué bon gré mal gré.

Le motif singleton n’est pas un problème en soi. Le problème est que le motif est souvent utilisé par les personnes développant des logiciels avec des outils orientés objet sans avoir une compréhension solide des concepts de OO. Lorsque des singletons sont introduits dans ce contexte, ils ont tendance à devenir des classes ingérables qui contiennent des méthodes d'assistance pour chaque petite utilisation.

Les singletons sont également un problème du point de vue des tests. Ils ont tendance à rendre les tests unitaires isolés difficiles à écrire. Inversion du contrôle (IoC) et injection de dépendance sont des modèles conçus pour résoudre ce problème de manière orientée objet et se prêtant aux tests unitaires. .

Dans un environnement nettoyé , les problèmes peuvent rapidement devenir un problème en ce qui concerne gestion de la mémoire.

Il existe également le scénario multi-thread dans lequel les singletons peuvent devenir un goulot d'étranglement ainsi qu'un problème de synchronisation.

Un singleton est mis en œuvre à l'aide d'une méthode statique. Les personnes qui font des tests unitaires évitent les méthodes statiques car elles ne peuvent être ni moquées ni écrasées. La plupart des gens sur ce site sont de grands partisans des tests unitaires. La convention la plus généralement acceptée pour les éviter consiste à utiliser le modèle inversion du contrôle .

Les singletons sont également mauvais en ce qui concerne le regroupement . Parce que dans ce cas, vous n’avez pas "exactement un singleton". dans votre application plus.

Considérez la situation suivante: en tant que développeur, vous devez créer une application Web qui accède à une base de données. Pour vous assurer que les appels de base de données simultanés ne se gênent pas, créez un SingletonDao :

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

Vous êtes donc sûr qu’un seul singleton existe dans votre application et que toutes les bases de données passent par ce seul et unique SingletonDao . Votre environnement de production ressemble maintenant à ceci: Singleton unique

Tout va bien jusqu'à présent.

Maintenant, considérez que vous souhaitez configurer plusieurs instances de votre application Web dans un cluster. Maintenant, vous avez soudainement quelque chose comme ça:

Plusieurs singletons

Cela semble étrange, mais votre candidature contient de nombreux singletons . Et c’est exactement ce qu’un singleton n’est pas censé être: avoir beaucoup d’objets. Ceci est particulièrement grave si, comme le montre cet exemple, vous souhaitez effectuer des appels synchronisés vers une base de données.

Bien sûr, il s’agit d’un exemple de mauvaise utilisation d’un singleton. Mais le message de cet exemple est le suivant: vous ne pouvez pas compter sur le fait qu’il existe une seule instance d’un singleton dans votre application, en particulier en ce qui concerne le clustering.

  1. Il est facilement (ab) utilisé comme variable globale.
  2. Les classes qui dépendent de singletons sont relativement plus difficiles à tester unitaire isolément.

Le monopole est le diable et les singletons dont l'état n'est pas en lecture seule / mutable sont le "vrai" problème ...

Après avoir lu les les singletons sont des menteurs pathologiques . comme suggéré dans la réponse de jason , je suis tombé sur cette petite info qui fournit le meilleur exemple présenté de comment les singletons sont souvent mal utilisés.

  

Global est mauvais parce que:

     
      
  • a. Cela provoque un conflit d’espace de noms
  •   
  • b. Il expose l'État d'une manière injustifiée
  •   
     

En ce qui concerne les singletons

     
      
  • a. La façon explicite d’appeler de ces objets empêche les conflits, alors point a. n'est pas un problème
  •   
  • b. Les singletons sans état sont (comme les usines) ne sont pas un problème. Les singletons avec state peuvent à nouveau appartenir à deux catégories, celles qui sont immuables ou qui écrivent une fois et lisent beaucoup (fichiers de configuration / propriété). Ce ne sont pas mauvais. Les singletons mutable, qui sont des types de détenteurs de références sont ceux dont vous parlez.
  •   

Dans la dernière déclaration, il fait référence au concept du blog "Les singletons sont des menteurs".

Comment cela s'applique-t-il au monopole?

Pour commencer une partie de monopole, commencez par:

  • nous établissons les règles en premier pour que tout le monde soit sur la même page
  • tout le monde a le même départ au début du jeu
  • un seul ensemble de règles est présenté pour éviter toute confusion
  • les règles ne sont pas autorisées à changer tout au long du jeu

Désormais, pour tous ceux qui n'ont pas vraiment joué le monopole, ces normes sont au mieux idéales. Une défaite en monopole est difficile à avaler, car le monopole est une question d'argent. Si vous perdez, vous devez regarder minutieusement le reste des joueurs terminer le match. Les pertes sont généralement rapides et écrasantes. Ainsi, les règles sont généralement tordues à un moment donné pour servir les intérêts personnels de certains joueurs au détriment des autres.

Vous jouez donc le monopole avec vos amis Bob, Joe et Ed. Vous construisez rapidement votre empire et consommez une part du marché à un taux exponentiel. Vos adversaires faiblissent et vous commencez à sentir le sang (au sens figuré). Votre copain, Bob, a investi tout son argent dans le plus grand nombre possible d’immeubles de faible valeur, mais il ne reçoit pas un retour sur investissement aussi élevé que prévu. Bob, par malchance, atterrit sur votre promenade et est excisé du jeu.

Le jeu passe désormais du jeu de dés amical aux affaires sérieuses. Bob a été cité en exemple d'échec et Joe et Ed ne veulent pas se retrouver comme "ce mec". Donc, en tant que joueur principal, vous devenez tout à coup l'ennemi. Joe et Ed commencent à s’exercer à des métiers clandestins, à des injections d’argent derrière le dos, à un échange de maison sous-évalué et à tout ce qui peut vous affaiblir en tant que joueur jusqu’à ce que l’un d’eux atteigne le sommet.

Ensuite, au lieu de gagner, le processus recommence à zéro. Soudainement, un ensemble fini de règles devient une cible mouvante et le jeu dégénère en un type d'interactions sociales qui constituerait le fondement de chaque émission de télé-réalité de premier plan depuis Survivor. Pourquoi, parce que les règles changent et qu'il n'y a pas de consensus sur comment / pourquoi / ce qu'elles sont censées représenter, et plus important encore, il n'y a pas une seule personne qui prend les décisions. Chaque joueur dans le jeu, à ce stade, établit ses propres règles et le chaos s'ensuit jusqu'à ce que deux des joueurs soient trop fatigués pour continuer la charade et abandonner lentement.

Ainsi, si un livre de règles pour un jeu représente avec précision un singleton, le livre de règles de monopole serait un exemple d’abus.

Comment cela s'applique-t-il à la programmation?

Mis à part tous les problèmes évidents de sécurité des threads et de synchronisation que les singletons mutables présentent ... Si vous avez un ensemble de données, celui-ci peut être lu / manipulé par plusieurs sources simultanément et existe pendant la durée de vie du fichier. l’exécution de l’application, c’est probablement le bon moment pour prendre du recul et demander: "est-ce que j’utilise le bon type de structure de données ici".

Personnellement, j’ai vu un programmeur abuser d’un singleton en l’utilisant comme une sorte de magasin de base de données cross-thread tordu au sein d’une application. Ayant travaillé directement sur le code, je peux attester qu'il était lent (à cause de tous les verrous de threads nécessaires pour le rendre thread-safe) et sur un cauchemar (en raison de la nature imprévisible / intermittente des bugs de synchronisation), et presque impossible à tester dans des conditions de «production». Bien sûr, un système aurait pu être développé en utilisant la polling / signalisation pour surmonter certains problèmes de performances, mais cela ne résoudrait pas les problèmes de tests et pourquoi s'inquiéter quand une "vraie" base de données peut déjà accomplir les mêmes fonctionnalités dans un environnement beaucoup plus robuste / de manière évolutive.

Un singleton est seulement une option si vous avez besoin de ce qu'un singleton fournit. Une instance en lecture seule d'un objet. Cette même règle devrait également se répercuter sur les propriétés / membres de l'objet.

Singleton ne concerne pas une instance unique!

Contrairement aux autres réponses, je ne veux pas parler de ce qui ne va pas avec les singletons, mais vous montrer à quel point ils sont puissants et géniaux quand ils sont utilisés correctement!

  • Problème : Singleton peut constituer un défi dans un environnement multi-thread

    Solution : utilisez un processus d'amorçage threadé unique pour initialiser toutes les dépendances de votre singleton.
  • Problème : Il est difficile de se moquer des singletons.
    Solution : utilisez la méthode modèle pour vous moquer
    . MyModel myModel = Factory.inject (MyModel.class); Vous pouvez mapper MyModel vers la classe TestMyModel qui en hérite, partout où MyModel sera injecté. Vous obtiendrez TestMyModel instread .
  • Problème : les singletons peuvent provoquer des poireaux de mémoire comme ils ne l'ont jamais été. Solution : Eliminez-les! Pour implémenter un rappel dans votre application afin de disposer correctement des singletons, vous devez supprimer toutes les données qui leur sont liées et enfin: les supprimer de la fabrique.

Comme je l'ai dit dans le titre, singleton ne concerne pas une instance unique.

  • Les singletons améliorent la lisibilité : vous pouvez regarder votre classe et voir quel singleton elle a injecté pour déterminer ses dépendances.
  • Les singletons améliorent la maintenance : une fois que vous avez supprimé une dépendance d'une classe, vous venez de supprimer une injection singleton, vous n'avez pas besoin de modifier un gros lien d'autres classes qui ont simplement déplacé votre dépendance. (C'est un code malodorant pour moi @Jim Burger .)
  • Singletons améliore la mémoire et les performances : lorsque quelque chose se produit dans votre application et qu'il faut une longue chaîne de callbacks, vous gaspillez de la mémoire et des performances. En utilisant Singleton, vous coupez le centre. et améliorez vos performances et votre utilisation de la mémoire (en évitant les allocations inutiles de variables locales).

Ma réponse sur la façon dont les singletons sont mauvais est toujours "ils sont difficiles à faire correctement". La plupart des composants de base des langages sont des singletons (classes, fonctions, espaces de noms et même opérateurs), de même que des composants d'autres aspects de l'informatique (localhost, route par défaut, système de fichiers virtuel, etc.), et ce n'est pas par hasard. S'ils causent parfois des ennuis et des frustrations, ils peuvent aussi faire beaucoup mieux le travail.

Les deux problèmes les plus importants que je vois sont les suivants: le traiter comme un outil global & amp; ne pas définir la fermeture singleton.

Tout le monde parle de Singleton en tant que globals, parce qu’ils le sont fondamentalement. Cependant, beaucoup (malheureusement pas tous) de la méchanceté dans un global ne provient pas intrinsèquement de la globalisation, mais de la façon dont vous l'utilisez. Il en va de même pour les singletons. En fait plus que "instance unique". n'a pas vraiment besoin de vouloir dire "accessible globalement". C'est plutôt un sous-produit naturel, et compte tenu de tout le mal dont nous sommes conscients, nous ne devrions pas être aussi pressés d'exploiter l'accessibilité mondiale. Une fois que les programmeurs voient un Singleton, ils semblent toujours y accéder directement via sa méthode d'instance. Au lieu de cela, vous devriez y accéder comme n'importe quel autre objet. La plupart des codes ne devraient même pas savoir qu'il s'agit d'un Singleton (couplage lâche, n'est-ce pas?). Si seulement un petit morceau de code accède à l'objet comme s'il s'agissait d'un global, beaucoup de dommages sont annulés. Je recommande de l'appliquer en limitant l'accès à la fonction d'instance.

Le contexte de Singleton est également très important. La caractéristique déterminante d’un Singleton est qu’il n’ya «qu’un», mais la vérité est qu’il n’ya «qu’un». dans une sorte de contexte / espace de nom. Ils sont généralement l’un des suivants: un par thread, processus, adresse IP ou cluster, mais peuvent également en être un par processeur, ordinateur, espace de noms de langage / chargeur de classe / peu importe, sous-réseau, Internet, etc.

L’autre erreur, moins fréquente, consiste à ignorer le mode de vie Singleton. Ce n’est pas parce qu’il n’en existe qu’un seul que Singleton est omnipotent "et a toujours été et sera toujours", et il n’est généralement pas souhaitable (les objets sans début ni fin violent le code de manière très utile, et doivent être utilisés seulement dans les circonstances les plus désespérées.

Si vous évitez ces erreurs, Singletons peut toujours être un PITA, mais il est prêt à résoudre de nombreux problèmes graves. Imaginez un Java Singleton, défini explicitement comme étant une fois par chargeur de classe (ce qui signifie qu'il a besoin d'une politique de sécurité des threads), avec des méthodes de création et de destruction définies, ainsi qu'un cycle de vie qui dicte quand et comment ils sont appelés, et dont "l'instance". La méthode a une protection de package, elle est donc généralement accessible via d’autres objets non globaux. Toujours une source potentielle de problèmes, mais certainement beaucoup moins.

Malheureusement, plutôt que d’enseigner de bons exemples sur la façon de faire des singletons. Nous enseignons de mauvais exemples, nous laissons les programmeurs les utiliser pendant un moment, puis nous leur disons qu’ils constituent un mauvais modèle.

Voir Wikipedia Singleton_pattern

  

Il est également considéré comme un anti-modèle par certaines personnes, qui estiment qu’il est trop utilisé, introduisant des limitations inutiles dans les situations où la seule instance d’une classe n’est pas réellement requise. [1] [2] [3] [3] [3] 4]

Références (uniquement les références pertinentes de l'article)

  1. ^ Alex Miller. Les motifs que je déteste # 1: Singleton , juillet 2007
  2. ^ Scott Densmore. Pourquoi les singletons sont diaboliques , mai 2004
  3. ^ Steve Yegge. Les chantiers considérés comme stupides , septembre 2004
  4. ^ J.B. Rainsberger, IBM. Utilisez judicieusement vos singletons , juillet 2001

Ce n’est pas que les singletons soient mauvais en soi, mais le modèle de conception GoF. Le seul argument réellement valable est que le modèle de conception GoF ne se prête pas au test, en particulier si les tests sont exécutés en parallèle.

L'utilisation d'une instance unique d'une classe est une construction valide tant que vous appliquez les moyens suivants dans le code:

  1. Assurez-vous que la classe qui sera utilisée en tant que singleton implémente une interface. Cela permet d’implémenter des stubs ou des mocks en utilisant la même interface

  2. Assurez-vous que le Singleton est thread-safe. C'est une donnée.

  3. Le singleton doit être de nature simple et pas trop compliqué.

  4. Pendant l'exécution de votre application, où des singletons doivent être passés à un objet donné, utilisez une fabrique de classes qui construit cet objet et demandez à la fabrique de classes de transmettre l'instance singleton à la classe qui en a besoin.

  5. Pendant les tests et pour assurer un comportement déterministe, créez la classe singleton en tant qu'instance distincte, en tant que classe réelle ou en tant que stub / mock qui implémente son comportement et transmettez-le tel quel à la classe qui en a besoin. N'utilisez pas le facteur de classe qui crée l'objet soumis au test qui a besoin du singleton pendant le test, car il passera son instance globale unique, ce qui irait à l'encontre du but recherché.

Nous avons utilisé Singletons dans nos solutions avec beaucoup de succès. Ils peuvent être testés pour garantir un comportement déterministe dans les flux de tests en parallèle.

Vince Huston a ces critères qui me paraissent raisonnables:

  

Singleton ne doit être envisagé que si les trois critères suivants sont remplis:

     
      
  • La propriété de l'instance unique ne peut pas être attribuée raisonnablement
  •   
  • L'initialisation paresseuse est souhaitable
  •   
  • L'accès global n'est pas prévu autrement
  •   
     

Si la propriété de l'instance unique, quand et comment l'initialisation a lieu, et si l'accès global n'est pas un problème, Singleton n'est pas suffisamment intéressant.

J'aimerais aborder les 4 points de la réponse acceptée. Si tout va bien, quelqu'un pourra expliquer pourquoi je me trompe.

  1. Pourquoi masquer les dépendances dans votre code est-il mauvais? Il existe déjà des dizaines de dépendances cachées (appels au runtime C, appels à l'API du système d'exploitation, appels de fonctions globales), et les dépendances singleton sont faciles à trouver (search for instance ()).

    "Créer quelque chose de global pour éviter de le transmettre est une odeur de code". Pourquoi ne pas transmettre quelque chose pour éviter d'en faire un singleton une odeur de code?

    Si vous transmettez un objet à travers 10 fonctions d'une pile d'appels pour éviter un singleton, est-ce si formidable?

  2. Principe de responsabilité unique: Je pense que ceci est un peu vague et dépend de votre définition de la responsabilité. Une question pertinente serait de savoir pourquoi l’ajout de cette spécifique " responsabilité " à une affaire de classe?

  3. Pourquoi le fait de passer un objet dans une classe le rend-il plus étroitement couplé que d'utiliser cet objet comme singleton à partir de la classe?

  4. Pourquoi cela change-t-il le temps que dure l'état? Les singletons peuvent être créés ou détruits manuellement, donc le contrôle est toujours là et vous pouvez rendre la durée de vie identique à celle d'un objet non-singleton.

En ce qui concerne les tests unitaires:

  • toutes les classes ne doivent pas nécessairement être unitaires testé
  • toutes les classes qui doivent être unitaires besoin testé de changer le implémentation du singleton
  • s'ils font doivent être testés à l'unité et faut-il changer la mise en œuvre, il est facile de changer une classe de en utilisant un singleton pour avoir le singleton est passé via dépendance injection.

Je ne vais pas commenter l'argument bon / mauvais, mais je ne les utilise plus depuis Le printemps est arrivé. L'utilisation de injection de dépendance a pratiquement supprimé mes exigences en matière de singleton, de servicelocators et d'usines. Je trouve cet environnement beaucoup plus productif et propre, du moins pour le type de travail que je fais (applications Web basées sur Java).

Il n’existe aucun problème inhérent au motif, à supposer qu’il soit utilisé pour un aspect vraiment unique de votre modèle.

Je pense que le contrecoup est dû à sa surutilisation, ce qui, à son tour, est dû au fait que c'est le modèle le plus facile à comprendre et à mettre en œuvre.

Les singletons sont mauvais d'un point de vue puriste.

D'un point de vue pratique, un singleton est un compromis entre temps de développement et complexité .

Si vous savez que votre application ne changera pas autant, son utilisation est acceptable. Sachez simplement que vous aurez peut-être besoin de modifier les choses si vos exigences changent de manière inattendue (ce qui est plutôt OK dans la plupart des cas).

Les singletons compliquent parfois les tests unitaires .

Singleton est un motif et peut être utilisé ou maltraité comme n'importe quel autre outil.

La mauvaise partie d'un singleton est généralement l'utilisateur (ou devrais-je dire l'utilisation inappropriée d'un singleton pour des choses pour lesquelles il n'est pas conçu). Le plus gros délinquant utilise un singleton comme fausse variable globale.

Lorsque vous écrivez du code à l'aide de singletons, par exemple un consignateur ou une connexion à une base de données, et que vous découvrez ensuite que vous avez besoin de plusieurs journaux ou de plusieurs bases de données, vous êtes en difficulté.

Les singletons rendent très difficile le déplacement d’objets normaux.

En outre, il est trop facile d’écrire un singleton sans fil thread-safe.

Plutôt que d’utiliser des singletons, vous devez passer tous les objets utilitaires nécessaires d’une fonction à l’autre. Cela peut être simplifié si vous les enroulez tous dans un objet utilitaire, comme ceci:

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}

Le problème des singletons est l’augmentation de leur portée et donc du couplage . Il est indéniable que dans certaines situations, vous devez avoir accès à une instance unique et que vous pouvez le faire de différentes manières.

Je préfère maintenant concevoir autour d'un conteneur Inversion de contrôle (IoC) et autoriser le les durées de vie devant être contrôlées par le conteneur. Cela vous donne l'avantage des classes qui dépendent de l'instance pour ignorer le fait qu'il existe une seule instance. La durée de vie du singleton peut être modifiée à l'avenir. Ce genre d’exemple que j’ai rencontré récemment était un simple ajustement, du simple thread au multi-thread.

FWIW, si c’est une PIA lorsque vous essayez de l’essayer à l’unité, il passe à PIA lorsque vous essayez de le déboguer, de le corriger ou de l’améliorer.

Article récent de Chris Reath sur ce sujet à l'adresse Codage sans commentaire .

Remarque: le codage sans commentaires n'est plus valide. Toutefois, l’article auquel le lien a été associé a été cloné par un autre utilisateur.

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx

Voici encore une chose à propos des singletons dont personne n’a encore parlé.

Dans la plupart des cas, "singletonity" est un détail d'implémentation pour une classe plutôt que caractéristique de son interface. L'inversion de Control Container peut masquer cette caractéristique aux utilisateurs de la classe; il vous suffit de marquer votre classe en tant que singleton (avec l'annotation @Singleton en Java par exemple) et c'est tout; IoCC fera le reste. Vous n'avez pas besoin de fournir un accès global à votre instance singleton, car l'accès est déjà géré par IoCC. Ainsi, il n'y a rien de mal avec IoC Singletons.

Les singletons GoF, opposés à IoC, sont supposés exposer les singletons "singletonity". dans l'interface via la méthode getInstance (), et afin qu'ils souffrent de tout ce qui précède.

Les singletons ne sont pas mauvais. Ce n’est que mauvais que de créer quelque chose d’unique au monde qui ne soit pas unique.

Cependant, il existe des "services de portée d'application". (pensez à un système de messagerie faisant en sorte que les composants interagissent) - cet APPEL pour un singleton, un "MessageQueue". - la classe qui a la méthode "SendMessage (...)".

Vous pouvez ensuite procéder comme suit:

MessageQueue.Current.SendMessage (new MailArrivedMessage (...));

Et bien sûr, faites:

MessageQueue.Current.RegisterReceiver (this);

dans les classes qui implémentent IMessageReceiver.

Trop de gens placent des objets qui ne sont pas thread-safe dans un motif singleton. J'ai vu des exemples de DataContext ( LINQ & nbsp; à} ) fait dans un modèle singleton, malgré le fait que le DataContext n’est pas thread-safe et est purement un objet d’unité de travail.

Comme il s’agit essentiellement de variables globales orientées objet, vous pouvez généralement concevoir vos classes de manière à ne pas en avoir besoin.

Une tendance se dégage lorsque plusieurs personnes (ou équipes) parviennent à des solutions similaires ou identiques. Beaucoup de gens utilisent encore des singletons dans leur forme originale ou utilisent des modèles d'usine (bonne discussion dans Modern C ++ Design d'Alexandrescu). La concurrence et la difficulté à gérer la durée de vie de l'objet sont les principaux obstacles, le premier pouvant être facilement géré comme vous le suggérez.

Comme tous les choix, Singleton a son lot de hauts et de bas. Je pense qu'ils peuvent être utilisés avec modération, en particulier pour les objets qui survivent à la durée de vie de l'application. Le fait qu’ils ressemblent (et le sont probablement) à des globaux a probablement déclenché les puristes.

Premièrement, une classe et ses collaborateurs doivent d’abord réaliser le but recherché plutôt que de se concentrer sur les déoendents. La gestion du cycle de vie (lorsque des instances sont créées et lorsqu'elles sortent du cadre) ne devrait pas faire partie de la responsabilité des cladses. La meilleure pratique acceptée consiste à concevoir ou à configurer un nouveau composant pour gérer les dépendances à l'aide de l'injection de dépendances.

Souvent, les logiciels deviennent de plus en plus compliqués, il est donc logique de disposer de plusieurs instances indépendantes du "singleton". classe avec un état différent. Commettre du code pour simplement saisir le singleton est une erreur dans de tels cas. Utiliser Singleton.getInstance () peut convenir à de petits systèmes simples, mais cela ne fonctionne pas et ne peut pas être étendu si on peut avoir besoin d’une instance différente de la même classe.

Aucune classe ne devrait être considérée comme un singleton, mais plutôt comme une application de son utilisation ou de la manière dont elle est utilisée pour configurer les dépendants. Cela n’a pas d’importance si l’on veut juste dire que les chemins de fichiers n’ont aucune importance, mais pour les plus grosses applications, ces dépendances doivent être décomposées et gérées de manière plus appropriée à l’aide de DI.

Les problèmes que les singleton rencontrent lors des tests sont un symptôme de leur environnement / cas d’utilisation unique codé en dur. La suite de tests et les nombreux tests sont chacun individuel et constituent un élément incompatible avec le codage en dur d'un singleton.

scroll top