J'ai lu des modèles de conception, par Gamma et al. J'ai une question concernant la méthode du modèle par rapport à l'injection de dépendance. P>
avec la méthode de modèle, vous "modèle" classes avec des politiques qui fournissent des alternatives aux actions ou calculs nécessaires. Donc, plutôt que de choisir une politique de plusieurs alternatives et de coder cette politique dans la classe, vous autorisez l'utilisateur de la classe à spécifier l'alternative qu'ils souhaitent utiliser. P>
Tout cela me semble très raisonnable. Mais j'ai frappé un peu de mur de briques conceptuelles. P>
Si vous instanciez une classe avec un objet de stratégie, l'objet de stratégie doit mettre en œuvre une interface abstraite. Le programmeur peut ensuite écrire des stratégies différentes qui compilent toutes les catégories sans erreur, car les stratégies implémentent l'interface. La classe utilisant les stratégies est codée à l'interface de stratégie et non à la mise en œuvre. P>
Si vous allez définir un abstrait Quelqu'un peut-il perdre une lumière sur la raison pour laquelle vous préférez la méthode du modèle à l'injection de dépendance? P> ipolicy code> pour ces objets de stratégie, pourquoi ne pas simplement utiliser l'injection de dépendance et passer dans le
ipolicy code> sur la construction? P>
3 Réponses :
La "méthode de modèle" dans votre cas (ne confondez pas avec le Modèle de modement de modèle ), ou appelons cela «injection de dépendance statique», éviterait la nécessité de fonctions virtuelles. Vous obtenez des performances principalement en donnant au compilateur des connaissances plus et définies, et donnez-lui donc une meilleure occasion d'optimisations. Les classes deviennent plus statiques et la sécurité de type est augmentée. P>
La taille de la classe peut potentiellement rétrécir (non ou réduit besoin de stocker des pointeurs). P>
Le vieil adage: p>
Ne payez pas pour ce que vous n'utilisez pas. p> blockQuote>
s'applique ici. Si vous n'avez pas besoin d'interfaces virtuelles, les modèles vous aident à les éviter sans sacrifier toute flexibilité. P>
OK, vous n'avez pas besoin d'une interface virtuelle, mais comment appliquez-vous l'interface des classes de stratégies sans un? C'est-à-dire comment indiquez-vous au programmateur quelles méthodes et propriétés la classe politique doit avoir pour fonctionner correctement lorsqu'il est injecté?
@Robinson Documentation. Sinon, il obtiendra des erreurs de compilation.
Je veux vraiment cocher tout ce qui précède comme "la réponse", mais je suis désolé de devoir aller avec l'exemple de Tom, ce qui a fait "cliquer" pour moi: p.
@Robinson: C'est parfaitement acceptable, vous êtes censé accepter la réponse qui a rendu le plus lourd que Click W.R.T. question :)
@Robinson Vous pouvez appliquer l'interface avec 'static_assert ()' (en C ++ 11 ou à partir de Boost)
@Robinson: Et à l'avenir, C ++ aura des concepts qui vous aident à assurer des contrats.
Premièrement, comme Phresnel mentionné, le modèle de méthode de modèle est pas em> un modèle au sens moderne. Lisez-la à nouveau, il utilise le polymorphisme d'exécution pour atteindre le même objectif pour lequel les algorithmes stl utilisent le polymorphisme de la compilation du temps (modèles de fonctions). P>
Deuxièmement, toutes sortes de polymorphes sont, dans un sens, une injection de dépendance. C'est-à-dire que l'appelant introduit l'algorithme au type concret sur lequel elle agit. La question ne pose donc généralement pas de savoir si vous pouviez ou si vous pouvez utiliser l'injection de dépendance à la place em> d'un autre modèle: le motif montre plutôt un moyen utile de structurer votre code à utiliser une injection de dépendance. P>
Si votre "dépendance injectée" est un paramètre de type de modèle, l'algorithme utilise la dactylographie du canard et vous n'avez pas à mettre en place une interface abstraite: juste écrire des méthodes avec la signature attendue. P>
Assez juste. Mais il n'ya aucun moyen de formaliser la signature prévue en tant que telle. Vous devez simplement avoir à lire la documentation.
@Robinson: L'absence d'une définition d'interface formelle explicite est considérée comme une force de ceux qui choisissent d'utiliser la typing de canard (et la programmation générique en C ++) et une faiblesse de ceux qui ne le font pas. Il y avait un effort pour obtenir des interfaces explicitement déclarées pour les modèles à C ++ 11 (il a été appelé «concepts»), mais il a été chuté car ce n'était pas suffisamment prêt.
Steve intéressant. Je me demande pourquoi cela serait considéré comme une faiblesse? Compte tenu de l'obscurité des messages d'erreur que vous rencontrez des compilateurs C ++ ces jours-ci, en particulier en ce qui concerne les modèles, j'aurais pensé que c'était une force pour ceux comme moi qui luttent pour "analyser" la sortie du compilateur!
@Robinson Il coupe les deux sens. Le problème des messages d'erreur obscure était en effet l'une des raisons les plus importantes de l'introduction de concepts. Il est généralement considéré comme une bonne pratique d'avoir une définition d'interface formelle. Une définition d'interface explicite i> peut parfois ajouter des chaudières significatives (et inutiles), car elle peut être facilement déduite. Dans l'ensemble, une interface explicite sur le côté du gabarit est généralement favorisée et est ce que les concepts nous auraient donnés. ...
... la deuxième question orthogonale, sur laquelle il y a eu la controverse que @steve a mentionné est la typing de canal, ce qui signifie que le utilisateur i> du modèle n'a pas besoin de déclarer explicitement que son type de paramètre remplit l'interface requise.
@Robinson - Vous devez en effet simplement lire la documentation (ou le code), mais cela semble fonctionner correctement pour Python. Pour référence, consultez les descriptions de concept dans l'ancien SGI STL Documentation: bien que cela puisse N'aidez pas avec le diagnostic du compilateur ou d'autres soirières que le soutien de la langue pour les concepts aurait apporté, c'est un bon exemple de décrivant clairement l'exigence afin qu'il soit facile à mettre en œuvre.
Concernant la "méthode du modèle" (plutôt que le modèle de conception), l'exemple suivant pourrait aider avec les avantages et les inconvénients pour décider quoi faire. L'exemple consiste à créer un mode verbeux d'une bibliothèque destiné à aider le débogage / le développement.
avec des modèles strong> p> L'utilisateur de la bibliothèque peut alors Écrire: P> struct printer
{
virtual void print(const std::string& msg) = 0;
}
struct console_print : public printer
{
void print(const std::string& msg) {std::cout<<msg;}
}
struct debug_print : public printer
{
void print(const std::string& msg) {}
}
Ah, d'accord, je vois les avantages maintenant. Ceci est en effet utile.
En outre, "où" vous préféreriez cela.
Passer la politique dans le constructeur est i> Injection de dépendance. Je ne comprends pas votre question.
Oui, c'est ce que j'ai dit dans la question. Mais la "méthode de modèle" est différente de di, mais aussi loin que je le vois, il a besoin de DI (temps de compilation) afin de travailler. Donc, la question était simplement pourquoi préfère tm à di?
Il n'y a pas de préférence ici. Vous utilisez simplement DI pour implémenter le modèle de méthode de modèle. Vous ne le préférez pas, vous utilisez les deux.
Répendants Veuillez noter: le «modèle de méthode de modèle» n'a absolument rien à voir avec les modèles C ++. C'est juste une coïncidence des noms.
Oui. C'est ce qu'on appelle "Modèle de modèle" dans le livre et peut être implémenté, je suppose avec des modèles C ++. Je pense que je l'ai vu en C ++ comme "conception basée sur la politique" et qui a utilisé des modèles pour injecter les politiques.
@Robinson: Yep, "Conception basée sur la stratégie" est le nom donné à quelque chose qui est essentiellement une utilisation des modèles pour mettre en œuvre une version du modèle de stratégie. Qui est étroitement liée au modèle de méthode de modèle. La plupart des motifs de conception inventés avec le polymorphisme d'exécution dans l'esprit peuvent être mis en œuvre à l'aide de polymorphisme statique en C ++, la méthode de modèle ne plus que d'autres.
OK, mon malentendu était avec DI, c'est-à-dire que je pensais que DI a été spécifiquement mis en œuvre en créant une interface, puis "injecter" la dépendance au moment de l'exécution, en C ++ via. passer un pointeur. En fait, DI est plus large que cela, et utiliser cette méthode n'est qu'une de plusieurs façons de le faire.