52 votes

Quand ne faut-il PAS utiliser le motif Singleton? (Outre l'évidence)

Je sais bien que vous souhaitez utiliser Singleton pour fournir un point d'accès à certaines etat ou de service. Les avantages d'un Singleton n'ont pas besoin d'être énumérées dans la présente question.

Ce qui m'intéresse, en sont les situations où Singleton peut sembler un bon choix au premier abord, mais peut revenir à vous mordre. Des fois, j'ai vu des auteurs de livres et d'affiches sur DONC dire que le pattern Singleton est souvent une très mauvaise idée.

La bande des Quatre états que vous aurez envie d'utiliser un Singleton lorsque:

  • il doit y avoir exactement une instance d'une classe, et il doit être accessible à tous les clients à partir d'un point d'accès connu.
  • lorsque la seule instance doit être extensible par sous-classement, et les clients doivent être en mesure d'utiliser une longue instance sans modification de leur code.

Ces points, certes notable, ne sont pas les pratiques qui je cherche.

Quelqu'un aurait-il un ensemble de règles ou de mises en garde que vous utilisez pour évaluer si vous êtes vraiment sûr que vous voulez utiliser un Singleton?

76voto

M2tM Points 2145

Résumé De La Version:

Vous savez combien de fois vous utilisez des variables globales? Ok, maintenant utiliser les Singletons ENCORE MOINS. Beaucoup moins en fait. Presque jamais. Ils partagent tous les problèmes globals ont caché de couplage (impactant directement la testabilité et la facilité de maintenance), et souvent la "seule peut exister" restriction est en fait une hypothèse erronée.

Réponse Détaillée:

La chose la plus importante à réaliser sur un singleton, c'est que c'est l'état global. Il est un modèle pour exposer une instance unique à l'échelle mondiale absolu d'accès. Cela a tous les problèmes de la programmation qui globals ont, mais adopte également intéressant de nouveaux détails de mise en œuvre et d'ailleurs très peu de valeur réelle (ou, en fait, il peut être inutile de faire des frais supplémentaires avec la seule instance aspect). La mise en œuvre est suffisamment différentes pour que les gens confondent souvent pour objet méthode d'encapsulation quand il est vraiment juste une fantaisie seule instance mondiale.

La seule situation dans laquelle vous devriez envisager un singleton, c'est quand avoir plus d'une instance de déjà données mondiale serait en fait une logique ou l'accès au matériel d'erreur. Même alors, vous devriez généralement pas traiter avec le singleton directement, mais au lieu de fournir une interface de wrapper qui est autorisé à être instancié autant de fois que vous le souhaitez, mais seulement accède à l'état global. De cette manière, vous pouvez continuer à utiliser l'injection de dépendance et si vous le pouvez jamais unmarry de l'état global du comportement de la classe à laquelle il n'est pas un changement radical dans l'ensemble de votre système. Il y a de subtiles questions avec ceci, cependant, quand il apparaît que si vous ne vous basez pas sur des données globales, mais vous êtes.

De sorte que (à l'aide de l'injection de dépendance de l'interface qui enveloppe le singleton) n'est qu'une suggestion et non une règle. En général, c'est encore mieux car au moins vous pouvez voir que la classe s'appuie sur le singleton alors que juste à l'aide de l' ::instance() la fonction à l'intérieur du ventre d'une fonction membre de classe se cache que la dépendance. Il permet également d'extraire les classes en s'appuyant sur l'état global et de mieux faire des tests unitaires pour eux, et vous pouvez passer dans la maquette de ne rien objets où si vous faites cuire la dépendance sur le singleton directement dans la classe, c'est BEAUCOUP plus difficile.

Un exemple d'un singleton peut être dans l'emballage d'une instance unique de style c interface comme SDL_mixer. Un exemple d'un singleton souvent naïvement mis en œuvre là où il ne devrait probablement pas être est dans une classe de log (ce qui se passe lorsque vous souhaitez vous connecter à la console ET sur le disque? Ou si vous voulez enregistrer les sous-systèmes séparément.)

Les problèmes les plus importants de compter sur l'état global, cependant, à peu près toujours venir quand vous essayez de mettre en œuvre correcte de tests unitaires (et vous devriez être en train d'essayer de le faire). Il devient alors beaucoup plus difficile à traiter votre demande lorsque les entrailles de classes que vous n'avez pas vraiment avoir accès à essaient de faire de vrai disque de l'écriture et de la lecture, de se connecter à un serveur en ligne et envoyer des données réelles, ou souffle le son de vos haut-parleurs bon gré mal gré. C'est beaucoup, beaucoup, mieux utiliser l'injection de dépendance, de sorte que vous peut se moquer d'un faire-rien de classe (et de voir que vous avez besoin de le faire dans le constructeur de la classe) dans le cas d'un plan de test et le point à ce, sans avoir à la divine tout l'état global de votre classe dépend.

Liens Connexes:

Motif de l'Utilisation vs Émergence

Les modèles sont utiles que des idées et des termes, mais, malheureusement, les gens semblent ressentir le besoin d'utiliser un modèle quand vraiment les modèles sont implémentés en tant que de besoin l'exige. Souvent, le singleton est spécifiquement entassé tout simplement parce que c'est souvent dans les discussions modèle. La conception de votre système avec une prise de conscience de modèles, mais ne pas la conception de votre système pour se plier à leur juste parce qu'ils existent. Ils sont utiles outils conceptuels, mais juste que vous n'avez pas à utiliser tous les outils dans la boîte à outils juste parce que vous le pouvez, vous ne devriez pas faire la même chose avec des motifs. Les utiliser comme il faut et pas plus ou moins.

14voto

Paul Rubel Points 13132

Un seul mot: test

Une des caractéristiques de la testabilité est un couplage lâche des classes, vous permettant d'isoler une seule classe et de le tester complètement. Quand une classe utilise un singleton (et je parle d'un classique singleton, qui applique sa propre singularité approfondie d'une méthode statique getInstance ()), le singleton de l'utilisateur et le singleton devenir étroitement couplés. Il n'est plus possible de tester l'utilisateur sans également des essais avec le singleton.

Les Singletons sont une catastrophe pour tester. Depuis qu'ils sont statiques, vous ne pouvez pas stub avec une sous-classe. Depuis qu'ils sont global, vous ne pouvez pas changer facilement la référence qu'ils point sans recompiler ou certains de levage lourd. Tout ce qui utilise le singleton comme par magie devient l'une des références mondiales de quelque chose qui est difficile à contrôler. De ce fait, il est difficile de limiter le champ d'application d'un test.

7voto

Lou Franco Points 48823

La plus grande erreur avec Singleton que j'ai vue est que vous concevez un système mono-utilisateur (par exemple, un programme de bureau) et utilisez Singleton pour beaucoup de choses (par exemple, Paramètres) et que vous voulez ensuite devenir multi-utilisateur, comme un site Web. ou un service.

Cela ressemble à ce qui est arrivé aux fonctions C avec des mémoires tampons statiques internes lorsqu'elles se sont habituées à des programmes multithreads.

5voto

WeNeedAnswers Points 1836

Je dirais d'éviter les singletons à tout prix. Il limite la mise à l'échelle des applications. Vraiment analyser le problème de votre traitement et de penser à l'évolutivité et à prendre des décisions fondées sur la façon évolutive vous souhaitez que votre application.

À la fin de la journée, un singleton agit comme une ressource goulot d'étranglement si elle est conçue de manière incorrecte.

Parfois vous présenter ce goulot d'étranglement sans bien comprendre quelles sont les implications de la suppression sur votre application.

J'ai rencontré des problèmes lorsque vous traitez avec des applications multi-thread qui tentent d'accéder à un singleton de ressources, mais entrer dans les blocages. C'est pourquoi j'essaie d'éviter un singleton autant que possible.

Si vous introduisez les singletons de votre conception, assurez-vous de comprendre l'exécution des implications, faire un peu de diagrammes et de comprendre d'où il pourrait causer un problème.

3voto

Steve Townsend Points 36948

Singleton est souvent utilisé comme un piège pour des choses que les gens ne peuvent être dérangés d'encapsuler correctement à l'endroit où ils sont réellement nécessaires, avec les accesseurs appropriés.

Le résultat final est une archive qui rassemble tous les static s du système. Combien de personnes ici n’ont JAMAIS vu une classe appelée Globals dans un code supposé OOD avec lequel elles ont dû travailler? Pouah.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X