Est-ce que les Singleton sont si mauvais? [dupliquer]

possibilité de dupliquer:

Qu'est-ce qu'il y a de si mal avec les Singleton?

il est compréhensible que beaucoup de modèles peuvent dans certains cas être abusés, et comme maman a toujours dit: " trop d'une bonne chose n'est pas toujours bon! "

je remarque que ces jours-ci, j'utilise beaucoup les Singletons, et je suis inquiet que je pourrais être abuser du modèle de conception moi-même, et courir de plus en plus profondément dans un type de mauvaise pratique de l'habitude.

nous développons une application Flex qui a une structure de données hiérarchiques assez importante conservée en mémoire pendant que l'utilisateur y travaille. L'utilisateur peut charger, enregistrer, modifier et rafraîchir les données à la demande.

ces données sont centralisées au moyen d'une classe Singleton, qui regroupe un couple de tableaux collecteurs, Tableaux, Objets de valeur et un autre natif variables de membre exposées via getters et setters.

pour obtenir une référence à nos données de n'importe où dans l'application, nous faisons le modèle entier.gettinstance () méthode type de chose, je suis sûr que tout le monde est familier avec. Cela garantit que nous obtenons toujours nos mains sur la même copie de données, puisque lorsque nous avons conçu, nous avons dit que seulement une instance est autorisée à exister pendant la durée de vie de l'application.

de ce dépôt central de données, il est alors facile pour nous à par exemple, la propriété d'expédition a changé les événements, et peut avoir de multiples composants D'interface utilisateur qui font référence aux données centrales, mettre à jour leurs affichages pour refléter les changements de données qui se sont produits.

jusqu'à présent, cette approche a été efficace et s'est avérée très pratique dans notre situation.

je trouve cependant que je suis un peu surmené en créant de nouvelles classes. Des Questions comme si une classe devait être unique, ou devrait-elle plutôt être gérée par une autre classe? comme utiliser une usine, par exemple, a tendance à devenir parfois un peu difficile, avec un peu d'incertitude.

Où puis-je tracer la ligne avec des Singleton? Est-il une bonne ligne de conduite pour décider quand utiliser les Singletons et quand rester loin d'eux.

aussi, est-ce que quelqu'un peut recommander un bon livre sur les modèles de design?

47
demandé sur Community 2009-06-20 02:26:18

12 réponses

L'essentiel à retenir est que les modèles de conception sont juste un outil pour vous aider à comprendre les concepts abstraits. Une fois que vous avez cette compréhension, vous limiter spécifiquement à une "recette" d'un livre est inutile et nuit à votre capacité d'écrire le code le plus approprié à votre but.

cela dit, la lecture de livres comme GoF vous présentera plus de façons de penser aux problèmes afin que lorsque le moment vient de mettre en œuvre quelque chose sur votre propre, vous avoir un ensemble plus large de points de vue pour aborder le problème.

dans votre cas, si utiliser singleton a du sens dans chaque cas, alors allez-y. Si cela convient "en quelque sorte" et que vous devez l'implémenter d'une manière quelconque, alors vous devez trouver une nouvelle solution. Forcer un modèle qui n'est pas parfait est un peu comme marteler une cheville carrée dans un trou rond.

étant donné que vous dites "cette approche a été efficace et s'est avérée très pratique pour notre circonstances," je pense que vous vous débrouillez bien.

Voici quelques bons livres:

Gang of four - le livre classique pour les modèles de conception

Head First Design Patterns - j'ai entendu ceci recommandé par quelques personnes comme une alternative

35
répondu mandaleeka 2009-06-19 22:35:41

Oui, les Singleton sont mauvais. Ils sont mauvais parce que tout ce qu'ils font pour vous est de combiner deux propriétés, dont chacune est mauvaise environ 95% du temps. (Ce qui signifie qu'en moyenne, les singletons sont des mauvais 99.75% du temps ;))

singleton", tel que défini par le GoF, est une structure de données qui:

  1. accorde l'accès global à un objet, et
  2. Applique qu'une seule instance de l'objet peut jamais exister.

la première est généralement considérée comme une mauvaise chose. Nous n'aimons pas les variables globales. La seconde est un peu plus subtile, mais en général, il n'y a pratiquement pas de cas où il s'agit d'une restriction raisonnable au enforce .

parfois, cela n'a de sens que d'avoir une instance d'un objet. Dans ce cas, vous choisissez de ne créer qu'un seul. Vous n'avez pas besoin d'un singleton pour l'appliquer.

Et en général, même lorsqu'il "a du sens" n'avoir qu'un seul exemple, il s'avère ne pas faire de sens, après tout. Tôt ou tard, vous allez avoir besoin de plus d'un enregistreur. Ou plus d'une base de données. Ou vous allez avoir à recréer des ressources pour chacun de vos tests unitaires, ce qui signifie que nous devons être en mesure de créer à volonté. Il supprime prématurément la flexibilité de notre code, avant que nous n'en comprenions les conséquences.

Singletons Cacher les dépendances et augmenter le couplage (chaque classe peut potentiellement dépendre d'un singleton, ce qui signifie que la classe ne peut pas être réutilisée dans d'autres projets à moins que nous réutilisions aussi tous nos Singleton), et parce que ces dépendances ne sont pas immédiatement visibles (comme les paramètres de fonction/constructeur), nous ne les remarquons pas, et typiquement n'y pensons pas quand nous les créons. C'est tellement facile de tirer juste dans un singleton, il agit presque comme une variable locale et tous, nous avons tendance à utiliser beaucoup une fois qu'ils sont là. Et cela les rend presque impossibles à enlever à nouveau. En fin de compte vous, peut-être pas avec le code spaghetti, mais avec les graphiques de dépendance spaghetti. Et tôt ou tard, vos dépendances de fuite signifieront que les singletons commencent à dépendre les uns des autres, et alors vous obtenez des dépendances circulaires quand on tente d'en initialiser une.

ils rendent extrêmement difficile le test unitaire. (Comment tester une fonction qui fait appel à des fonctions sur un objet singleton? Nous ne voulons pas que le vrai code singleton soit exercé, mais comment pouvons-nous empêcher cela?

Oui, les Singleton sont mauvais.

parfois, on veut vraiment un global. Alors utilisez un global, pas un singleton.

parfois, très très très rarement, vous pouvez avoir une situation où la création d'instances multiples d'une classe est une erreur, où il peut ne peut pas être fait sans causer des erreurs. (Sur le seul cas que je peux penser, et même qui est inventé, est si vous représentez un dispositif matériel. Vous n'avez qu'un seul GPU, donc si vous êtes va correspondre à un objet dans votre code, il serait logique qu'une seule instance peut exister). Mais si vous vous trouvez dans une telle situation (et encore une fois, pour souligner, une situation où plusieurs instances causent de graves erreurs, pas seulement une situation où "je ne peux penser à aucun cas d'utilisation pour plus d'une instance"), alors appliquez cette contrainte, mais faites-le Sans aussi rendre l'objet globalement visible.

Chacun de ces deux propriétés peut utiles, dans de rares cas. Mais je ne peux pas penser à un seul cas où la combinaison serait une bonne chose.

malheureusement, beaucoup de gens ont eu l'idée que "les Singletons sont des globals compatibles OOP."Non, ils ne le sont pas. Ils souffrent encore des mêmes problèmes que les globals, en plus à l'introduction d'autres, complètement sans rapport. Il n'y a absolument aucune raison de préférer un singleton à un simple Vieux global.

107
répondu jalf 2009-06-19 22:55:24

les développeurs de logiciels semblent être divisés assez également en deux camps, selon qu'ils favorisent un style de codage idéaliste ou pragmatique:

  • Idéaliste: Jamais utiliser le pattern singleton.
  • Pragmatique: Éviter le pattern singleton.

personnellement, je suis favorable à l'approche pragmatique. Parfois, il est logique d'enfreindre les règles, mais seulement si vous comprenez vraiment ce que vous faites et qui sont disposés à accepter les risques associés. Si vous pouvez répondre "oui" aux questions ci-dessous concernant votre cas d'utilisation spécifique, le modèle singleton peut apporter quelques avantages pratiques.

  • le singleton est-il externe à votre application? Les bases de données, les services de mise en file d'attente et les ESB sont tous des exemples macro parfaitement valables du modèle singleton.
  • KISS: est-ce que vous l'application entière limitée à 2-3 interne les singletons?
  • à SEC: ce Sont les singletons mondial par nature et entraînerait donc avoir à l'aplomb des références dans, presque tous les objets dans votre application? (par exemple, un enregistreur ou d'un composant médiateur)?
  • vos singletons dépendent-ils seulement les uns des autres, et/ou de l'environnement d'exploitation?
  • avez-vous veillé à ce qu'il y ait des séquences de démarrage et d'arrêt adéquates pour chaque singleton, y compris des considérations de gestion de la mémoire? Par exemple, un " Grand Central " - style thread pool peut avoir besoin d'avoir des méthodes run instance() et Shutdown() dans main() pour que les tâches soient garanties de ne s'exécuter que lorsque les objets sur lesquels elles fonctionnent sont dans un état valide.
14
répondu kgriffs 2012-04-26 16:34:50

les Singletons ne tuent pas les programmes, les programmeurs tuent les programmes.

comme toute construction de programmation, lorsqu'il est utilisé de manière appropriée, vous ne vous tirerez pas dans le pied.

les livres recommandés sont très bien, mais ils ne donnent pas toujours assez de fond qui vient avec l'expérience sur quand vous pourriez faire le choix D'utiliser Singleton.

cette expérience ne vient que lorsque vous avez trouvé Singleton est un mauvais choix quand vous avez besoin de plusieurs instances, et tout d'un coup, vous avez beaucoup de mal à injecter de l'objet de références partout.

il est parfois préférable d'aller de l'avant et d'avoir les références de l'objet en place, mais le fait que vous utilisez Singleton à tous les aider à identifier l'ampleur du problème que vous feriez face si vous avez à refactor il à un design différent. Je pense que c'est une très bonne chose, c'est-à-dire que le simple fait d'avoir une classe (même si elle est mal conçue) donne une certaine capacité à voir les effets d'un changement de la classe.

9
répondu Cade Roux 2009-06-19 22:42:17

Nous avons commencé un projet où nous sommes confrontés à la même question, qui est, comment accéder au modèle , et surtout son élément racine. Le projet n'est pas un Flex app, mais un jeu! application web, mais ça n'a pas vraiment d'importance.

Ayant une objet unique dans le système est très bien, le problème est comment accéder à . Le débat sur singleton est donc lié à la notion de l'injection de dépendance (DI), et comment obtenir des objets.

Les principaux arguments pour les DI sont les suivantes:

  • testabilité et moquerie
  • découplage de l'instanciation de l'objet de l'utilisation (qui peut conduire à la gestion du cycle de vie)
  • séparation des préoccupations

approches possibles pour le DI sont (Voir le classique article de Fowler):

  • faire circuler l'objet dans les paramètres de la méthode
  • Localisateur de service
  • DI-cadre

dans cette perspective, le modèle singleton n'est qu'une sorte de localisateur de service, par exemple Model.getInstance() .

mais pour fournir un maximum de flexibilité face aux changements futurs, la référence à l'objet unique doit être passé autour de autant que possible, et obtenu avec Model.getInstance() seulement si nécessaire. Cela donnera aussi du code plus propre.

4
répondu ewernli 2018-10-04 03:28:05

à mon avis, l'utilisation de Singletons signale directement un défaut de conception. La raison en est simplement qu'ils permettent de contourner les mécanismes normaux de création et de destruction d'objets intégrés dans C++. Si un objet a besoin d'une référence à un autre objet, il devrait passer dans une référence lors de la construction ou de créer une nouvelle instance de l'interne. Mais quand vous utilisez un singleton, vous obscurcissez explicitement le cycle de création et de démontage. Un problème connexe est qu'il est extrêmement difficile de contrôler la vie d'un singleton. En conséquence, de nombreux paquets qui incluent des implémentations singleton génériques incluent aussi des gestionnaires de durée de vie d'objets clunky et autres. Parfois, je me demande si elles n'existent pas simplement pour gérer les Singleton.

fondamentalement, si vous avez besoin d'utiliser un objet à de nombreux endroits, il doit être créé explicitement au point commun le plus élevé de la pile et ensuite transmis par référence à tous ceux qui l'utilise. Parfois, les gens utilisez Singletons parce qu'ils ont des problèmes en passant plusieurs args à de nouveaux threads, mais ne tombez pas dans le panneau, définissez explicitement vos args de thread et passez-les au nouveau thread de la même manière. Vous constaterez que votre programme est beaucoup plus propre et qu'il n'y a pas de mauvaises surprises en raison de dépendances statiques d'initialisation ou de démontage erroné.

3
répondu Andy B 2010-08-14 00:20:27

Singletons sont certainement pas mauvais. Ils ont leurs usages, certains très bons. Les Singletons ont tendance à être surutilisés par les développeurs inexpérimentés car c'est souvent le premier patten de design qu'ils apprennent, et c'est assez simple, donc ils le balancent partout sans penser aux implications.

chaque fois que vous voulez utiliser un singleton, essayez de considérer pourquoi vous le faites, et quels sont les avantages et les inconvénients de l'utilisation de ce modèle.

les Singletons créent effectivement un ensemble global accessible de 'stuff' (données ou méthodes) et je pense que la plupart des gens conviendraient que l'utilisation de trop de variables globales n'est pas une bonne idée. Le but des classes et de l'orientation des objets est de grouper les choses en zones discrètes plutôt que de tout balancer dans un espace global massif.

L'un des "motifs" que j'ai tendance à préférer aux singletons est de faire passer des objets haut. Je les crée une fois au cours de ma phase d'initialisation des applications, et je les transmets à travers tous les objets qui ont besoin d'y accéder. Il imite la seule création d'un pattern singleton, mais sans le "global".

le but d'un singleton est que c'est pour les objets où seulement un devrait jamais exister. Vous mentionnez un ensemble de classes de contrôle des données. Peut-être considérer qu'en fait, il ya des cas où une application pourrait vouloir créer 2 ensembles de contrôle des données les classes, donc peut-être que forcer un singleton à faire ça n'est pas tout à fait juste. Au lieu de cela, si vous avez créé ces classes de données sur app init, et que vous les avez transmises, vous ne créez que 1 set car c'est ce dont votre application actuelle a besoin, mais vous laissez ouverte la possibilité qu'à un moment donné, si vous avez besoin d'un second jeu, vous puissiez facilement les créer. En outre, si les classes de contrôle de données sont réellement accessibles globaly de n'importe où dans l'application. Je ne pense pas, mais ils devraient probablement être accessibles à partir d'un niveau inférieur couche d'accès aux données.

certaines personnes ont recommandé le livre GOF. Je dirais, oui c'est un grand livre, mais d'abord essayer de trouver un livre sur l'architecture générale d'abord, lire sur 2/3/n-tier design, encapsulation, abstraction, et ce genre de principes d'abord. Cela vous donnera une base solide pour comprendre l'utilisation appropriée des patterns du GOF parler.

[Edit: l'autre fois qu'une variante singleton peut être utile est quand vous voulez un point d'accès unique à quelque chose, mais le détail de la mise en œuvre pourrait en fait être plus d'une chose. L'appelant n'a pas besoin de savoir, que sous les couvertures leur demande pour l'objet singleton est en fait résolu contre plusieurs objets disponibles et un est retourné. Je pense à quelque chose comme une piscine de fil ici, où l'utilisation va, hey, juste obtenir moi un fil, j'ai besoin de 1, mais je ne me soucie pas lequel]

2
répondu Simon P Stevens 2009-06-19 22:51:52

je sais que c'est un vieux fil, mais personne ne semblait mentionner le motif réel qui correspond à ce que l'opération tentait de faire. Ce que je crois qu'il décrit comme un besoin est appelé le modèle de médiateur . SourceMaking est un site fantastique pour apprendre / référencer ce genre d'information. Certainement mon go to place pour introduire les gens aux modèles de logiciels. Aussi, il est généralement une bonne idée de ne pas acheter dans la notion que tout modèle de conception est nécessairement intrinsèquement bon ou mauvais. Ils ont tous leur utilité, c'est seulement apprendre quand et où les utiliser qui est l'astuce. Les gens qui déclarent ne jamais utiliser les Singletons, pour moi, ne comprennent pas leur utilité.

2
répondu tnicks 2012-05-11 15:17:34

Non, ils ne sont pas nécessairement mauvais.

comme pour un livre, vous devez commencer par le classiques .

0
répondu Stu 2009-06-19 22:27:54

Singletons ne sont pas "mauvais". Si vous avez beaucoup de Singleton liés et vous pouvez remplacer/consolider un certain nombre d'entre eux en utilisant une usine, sans perdre quoi que ce soit que vous vous souciez, alors c'est alors que vous devriez le faire.

en ce qui concerne les livres, Eh bien, il y a une sorte de canon .

0
répondu chaos 2009-06-19 22:30:02
0
répondu Jeff Meatball Yang 2009-06-19 22:32:48

Google semble être convaincu que les Singletons sont une mauvaise idée.

ce n'est pas pour suggérer que tout ce que Google fait est parfait ou que chaque opinion est la fin de n'importe quel argument, mais ils sont allés jusqu'à écrire ce détecteur de Singleton pour les extirper. Faire votre propre avis.

0
répondu duffymo 2009-06-20 01:09:43