“Singleton” usines", bon ou mauvais?
J'ai beaucoup de (résumé) les usines et ils sont généralement mis en œuvre comme des singletons.
Généralement pour la commodité de ne pas avoir à passer à travers les couches qui n'ont vraiment pas d'affaires avec l'aide ou la connaissance de ces usines.
La plupart du temps, j'ai seulement besoin de prendre une décision au démarrage dont l'usine de mise en œuvre, le reste du programme du code d', peut-être par le biais de certains de configuration
il semble par exemple comme
abstract class ColumnCalculationFactory {
private static ColumnCalculationFactory factory;
public static void SetFactory(ColumnCalculationFactory f) {
factory = f;
}
public static void Factory() {
return factory;
}
public IPercentCalculation CreatePercentCalculation();
public IAverageCalculation CreateAverageCalculation();
....
}
Quelque chose ne sentent à ce sujet, je ne suis pas sûr de ce que - c'est peut-être plus d'un disuised global qu'un singleton. C'est pas comme si il n'y a vraiment vraiment ont pour être une seule usine jamais de création de ColumnCalculations - bien que mes programmes n'ont pas besoin de plus.
Est-ce considéré comme le meilleur practuce ? Devrais-je plutôt des trucs dans une (semi) global AppContext classe ? Quelque chose d'autre(je ne suis pas tout à fait prêt à passer à une plus grande conteneur IoC, ou spring.net tout à fait encore d'ailleurs) ?
Vous devez vous connecter pour publier un commentaire.
Cela dépend vraiment de ce que vous faites et la portée de votre application. Si c'est juste de la taille relativement petite de l'application et il ne va pas croître au-delà de cela, alors votre approche actuelle pourrait bien être fine. Il n'est pas universelle "meilleure pratique" pour ces choses. Bien que je ne recommande pas d'utiliser des singletons pour autre chose que des apatrides, des feuilles, des méthodes et/ou téléphoniques (exploitation forestière, par exemple), de le rejeter hors de la main "juste parce que" c'est un singleton n'est pas forcément la bonne chose à faire.
Pour rien d'autre que négligeable ou prototype code, personnellement, j'aime utiliser explicitement l'inversion de contrôle avec le constructeur d'injection, car cela signifie que toutes les dépendances soient pris en compte et vous n'obtenez pas de 'surprises'. Le compilateur ne vous laisseront pas de les instancier Un sans B et B sans C. Singletons immédiatement enterrer ces relations -- vous pouvez instancier Un sans B et B sans C. Lors de l'appel de A à B se produit, vous obtenez une référence nulle exception.
C'est particulièrement gênant lors de l'essai, comme vous l'avez de manière itérative le travail de retour sur la runtime échecs. Lorsque vous testez le code, vous êtes à l'aide de l'API comme un collègue programmeur faire, donc c'est révélatrice de la conception des problèmes avec cette approche. Constructeur injection assure cela ne peut jamais arriver, toutes les dépendances sont énoncés à l'avant. L'inconvénient avec le constructeur de l'injection, c'est que la configuration de votre objet graphique est plus compliqué. Ceci est atténué par l'utilisation d'un conteneur IoC.
Je suppose que ce que j'essaie de dire, c'est que si vous avez à l'endroit où vous envisagez de l'utiliser un certain type de contexte, objet et un modèle de registre, vous pourriez aussi bien avoir un coup d'oeil au Cio des conteneurs. D'aller à l'effort de roulement de votre propre mutt version est probablement une perte de temps lorsque vous pouvez utiliser un produit gratuit, comme Autofac.
Avoir un peu de singletons est assez typique et n'est généralement pas problématique--beaucoup de singletons, conduit à des irritants code.
Nous vient de traverser une situation où nous avons eu à tester notre lourdement singleton chargés de cours. Le problème est que lorsque vous effectuez des essais de catégorie b, et il obtient la classe c (un singleton), vous n'avez aucune façon de se moquer de la classe c (Au moins EasyMock ne nous permet pas de remplacer la statique de l'usine de méthode d'une classe singleton.
Une solution simple est d'avoir des "Poseurs" pour tous vos singletons des fins de test. Pas vraiment recommandé.
Une autre chose que nous avons essayé était pour une classe unique, qui a tenu tous les singletons--un registre. Cela est d'obtenir assez proche de l'injection de dépendance, ce qui est presque certainement utiliser.
Côté de tester, j'ai appris il y a longtemps que quand il n'y a jamais jamais jamais y avoir plus d'une instance d'un objet donné; dans la prochaine rev ils veulent souvent deux, ce qui rend les singletons BEAUCOUP mieux que les classes statiques--au moins, vous pouvez ajouter un paramètre à la lecture d'un singleton et retourner une seconde sans trop de refactoring (qui est encore une fois juste à faire ce que DI t).
En tout cas, regardez-DI, vous pourriez être très heureux.
Non, parce que ce que vous faites ici est la création de l'état global. Il y a toutes sortes de problèmes avec l'état global - chef d'entre eux qui a une fonction puis dépend plutôt de manière invisible sur le comportement des autres fonctions. Si une fonction en appelle une autre fonction qui oublie de stocker et restaurer la
factory
avant la fin, alors vous avez un problème parce que vous ne pouvez même pas obtenir de l'ancienne valeur, sauf si vous l'avez stocké quelque part. Et vous devez ajouter du code pour le faire (à en juger par votre code, je suppose que vous êtes dans une langue avecfinally
, ce qui laisse encore plus de place pour des erreurs). De plus, si vous vous retrouvez avec le code qui a besoin de basculer entre les deux usines rapidement pour les deux sous-objets, vous devez écrire un appel de méthode à chaque point que vous ne pouvez pas stocker l'état de chaque sous-objet (eh bien, vous pouvez, mais vous l'encontre de la finalité de l'état global [qui, certes, n'est pas beaucoup]).Il a probablement fait le plus de sens pour stocker le type d'usine en tant que membre, et de la passer au constructeur de nouveau les objets qui en ont besoin (ou en créer un nouveau en tant que de besoin, etc.). Il vous donne également un meilleur contrôle - vous pouvez garantir que tous les objets construits par l'objet A est passé par la même usine, ou vous pouvez offrir des méthodes pour swap usines.
Je ne vois pas de problème: vous avez dit "mes programmes n'ont pas besoin de plus", donc votre mise en œuvre de quelque chose de plus souple/abrégé peut être un cas de Vous Ain't Gonna Besoin.
Je ne vous le conseille, car il est très difficile d'écrire décent, des tests unitaires pour le code qui appelle ces usines.
Misko Hevery a un l'article de nice à ce sujet sur son blog.
La mauvaise forme de singleton est celui qui met en œuvre l'équivalent de votre méthode de Fabrique avec:
C'est beaucoup plus difficile à talon, de se moquer ou de la pellicule.
La version qui renvoie un objet créé est beaucoup mieux, même si, comme pour la plupart rien, peut être mal utilisé ou utilisé de façon excessive.