Il y a beaucoup de questions sur si les singletons sont "mauvais" et quels modèles à utiliser à la place. Ils sont généralement concentrés sur le modèle de conception singleton, qui implique la récupération de l'instance Singleton à partir d'une méthode statique de la classe. Ce n'est pas une de ces questions. P>
Depuis que j'ai vraiment "découvert" une injection de dépendance de plusieurs mois, je conduis son adoption dans notre équipe, en supprimant les modèles statiques et singletons de notre code au fil du temps et en utilisant une injection basée sur le constructeur dans la mesure du possible. Nous avons adopté des conventions afin de ne pas avoir à continuer d'ajouter des liaisons explicites à nos modules DI. Nous utilisons même le document DI pour fournir des instances d'enregistrement, afin que nous puissions raconter automatiquement chaque enregistreur que la classe est sans code supplémentaire. Maintenant que j'ai un seul endroit où je peux contrôler la manière dont différents types sont liés, il est très facile de déterminer ce que le cycle de vie d'une catégorie de classes particulière (classes utilitaires, référentiels, etc.) devrait être. P>
Ma pensée initiale était qu'il y aurait probablement d'avantages pour lier des cours comme singletons si je m'attendais à ce que ceux-ci soient utilisés équitablement souvent. Cela signifie simplement qu'il y a beaucoup moins Puis j'ai lu "singleton je t'aime, mais tu m'appelles" sur www.codingwithoutkcommkments.com, et cela m'a fait me demander si j'avais la bonne idée. Après tout, les fonctions de création d'objets de NIJECT mettent en valeur par défaut, il y a donc très peu de frais de réflexion impliqués dans la création d'instances supplémentaires de ces objets. Parce que nous gardons la logique d'entreprise hors du constructeur, la création de nouvelles instances est une opération très légère. Et les objets n'ont pas de champs de champs non statiques, il n'ya donc pas beaucoup de mémoire de mémoire impliquée dans la création de nouvelles instances, non plus. P>
Donc, à ce stade, je commence à penser que cela n'aura probablement pas d'importance majeure de toute façon. Y a-t-il des considérations supplémentaires que je n'ai pas pris en compte? Quelqu'un a-t-il réellement connu une amélioration significative de la performance en modifiant les cycles de vie de certains types d'objets? Suivre le modèle DI la seule chose réelle importante, ou existe-t-il d'autres raisons que l'utilisation d'une seule instance d'un objet peut être intrinsèquement "mauvaise" p> nouveau code> en cours, surtout lorsque l'objet que vous créez finit par une grosse arborescence de dépendance. À peu près, les seuls champs non statiques de l'une de ces classes sont ces valeurs qui se sont injectées dans le constructeur. Il y a donc relativement peu de mémoire au-dessus de la mémoire pour garder une instance autour de ce qui n'est pas utilisé. P>
4 Réponses :
Cela ne devrait pas comporter beaucoup pour l'utilisation de la mémoire, mais vous obtiendrez une modularité accrue, une testabilité plus facile avec des objets graves et la laideur esthétique de devoir rédiger des dépendances explicitement encourageront les programmeurs à rendre chaque classe plus orthogonale et indépendante. Il est plus facile de briller sur les dépendances lorsque votre classe appelle les globaux, qu'un singleton est fondamentalement, et cela peut rendre votre vie plus difficile plus tard. P>
Je ne pense pas que vous avez compris ma question. Je am i> à l'aide de l'injection de dépendance, le code sera donc exactement de la même manière. La question est de savoir si les objets injectés devraient réellement être le même exemple à chaque fois, ou s'il existe un avantage d'avoir une nouvelle instance remise à chaque classe.
Oh, dans ce cas, il doit y avoir plus d'informations pour répondre correctement à votre question. Si les objets passés n'ont pas d'état, il n'y a pas de différence à l'exception de la référence supplémentaire d'objet requise pour effectuer une nouvelle instance. S'ils le font, alors cela dépend de vos besoins et de ce que vous attendez-vous.
Les objets n'ont pas l'état de l'extérieur des autres services injectés, qui sont stockés comme des champs privés. Donc, il y a potentiellement un gros arbre de Nouveau code> à chaque fois qu'un service est créé, mais c'est à peu près tout.
Je ne sais pas si la gestion de la mémoire est la grosse émission que si vous créez beaucoup d'objets. J'ai trouvé utiliser Singleton à partir de mon conteneur IOC utile lorsque vous traitez de quelque chose comme la mise en cache, où la création de l'objet de mise en cache et une connexion aux serveurs de mise en cache est coûteuse pendant la création afin de créer une fois l'objet de mise en cache et de la réutiliser. P>
Une seule instance peut être nocive mais car il peut créer un goulot d'étranglement dans la performance, car vous disposez d'une seule instance servant plusieurs demandes dans le cas des services. p>
Pouvez-vous élaborer ce deuxième paragraphe? En supposant que mes classes soient écrits de manière à ce que chaque méthode soit encapsulée, la sécurité du thread ne soit pas un problème (je n'ai pas à faire des serrures ni rien), comment peut-il ralentir les choses d'avoir une instance de servir plusieurs demandes?
Si vous êtes en sécurité, il n'ya rien à craindre aussi loin que je connais. Ma première tentative avec le CIO Un moment de retour m'a frappé avec ce problème. Depuis lors, j'utilise Singleton pour de nombreux services et les faire filer en toute sécurité.
Comme indiqué dans La réponse de Gary , tout le point de DI est la testabilité (vous pouvez facilement vous moquer de toutes les références à une classe puisqu'elles sont toutes répertoriées dans le constructeur), et non des performances d'exécution. P>
vous veux strong> pour faire TDD (Développement du lecteur d'essai), non? P>
Comme indiqué dans mon commentaire sur la réponse de Gary (écrit avant de répondre), et dans le titre, et encore une fois le corps de la question: J'utilise une injection de dépendance i>. Je ne pose pas de question sur le "modèle" singleton, mais plutôt s'il existe un avantage à lier mes services comme Singleton par rapport à transitoire dans le module de configuration DI.
Je vois. Je pense toujours que la performance ne devrait pas être la principale préoccupation ici. Je recommanderais d'utiliser la solution qui rend votre code le plus facile à lire. Vous dites que vous utilisez le cadre de votre DI pour les enregistreurs; Cela semble un gain de lisibilité (moins encombrement dans les classes). Pour d'autres cas, l'inverse pourrait être vrai; Vous voudrez peut-être être explicite si le service indique au cycle de la classe / cycle de vie / catégorie.
Parce que j'utilise di et liant par convention, je peux ajouter .insingletonscope () code> à une ligne de code, et toutes mes classes de référentiel seront magiquement singletons, même si je continue à utiliser une injection de dépendance pour leur fournir des cours qui en ont besoin. Grâce au cadre DI, la lisibilité du code ne sera pas affectée dans les deux sens. Je conviens que la performance n'est pas une grande préoccupation, alors ma question est de savoir s'il existe d'autres préoccupations que je devrais garder à l'esprit lors de la prise de cette décision.
J'utilise des instances Singleton pour mettre en cache coûteuse pour créer des objets (comme Nibernate Session Factory) ou pour des objets que je souhaite partager sur l'application. P>
Si dans l'incertitude, je préférerais que l'objet soit recréé à chaque fois qu'il soit utilisé et le marquez comme singleton ou "par fil" / "par demande" / "par anow quoi que ce soit" seulement si vous n'avez vraiment pas besoin. P>
Sparter des singletons sur le lieu de sauvegarde potentiellement une nouvelle optimisation prématurée et peut conduire à des bugs vraiment désagréables car vous ne pouvez pas être sûr que l'objet est nouveau ou partagé sur plusieurs objets / instances. p>
Même si l'objet n'a aucun état pour le moment et semble être enregistré pour partager, quelqu'un peut refroidir plus tard et y ajouter un État qui peut être partagé involontairement entre différents objets / instances. P>