J'ai un ensemble de classes, dont chacune doit décider à un moment ou l'autre de deux ou trois approches à utiliser en interne pour implémenter la même fonctionnalité de manière externe. Idéalement, ceci devrait inclure une fonctionnalité de repli, où si ApproachA échoue, il échoue pour essayer ApproachB (et peut-être approche C, D, etc.). Jusqu'à présent, je viens d'utiliser le codage comme if (!success) { ApproachB code }
. Le problème avec ceci est que plusieurs méthodes ultérieures doivent également être conscientes de l'approche qui a été choisie et toutes développent également leurs propres instructions. Je veux vraiment résoudre le problème avec quelque chose de moins lourd ... sauf qu'aucune des autres options que j'ai considérées ne semble être «maniable». Voici les trois approches auxquelles j'ai pensé:Implémentation de classes "de repli"
- Implémentez une méthode .Create statique qui détermine laquelle des deux classes dérivées à créer, où les deux classes ont une interface qui les sauvegarde. L'inconvénient de ceci est que vous écrivez beaucoup deux fois le même code, et que cela ne crée pas vraiment de "repli", car cela oblige à prendre toutes les décisions à l'avance dans la méthode .Create. Cela devrait fonctionner 9/10 fois, mais il y aura l'autre 1/10 fois où je veux que le repli ne démarre que lorsque le primaire a essayé et échoué.
- La même chose que ci-dessus, mais avec une classe de base ou abstraite impliquée, soit comme classe de support pour les deux, soit avec la classe primaire comme classe de base pour le repli. Cela a le même désavantage de repli, mais au moins il y a peu ou pas de code répété.
une classe abstraite Mettre en oeuvre normalement construit avec des classes d'enfants qui peuvent être modifiés à l'exécution: à savoir
public void SomeMethodOrConstructor() { if (someConditions) MyChild = ChildClassA; else MyChild = ChildClassB; } public void Execute() { MyChild.Execute(); }
Le problème avec l'option 3 est le passage de données entre les deux en cas de besoin. Puisque certaines de ces méthodes modélisent des objets extérieurs, cela sera assez fréquent. Les classes imbriquées partagent-elles automatiquement les données avec leur classe parente? Ou devrais-je passer le tout à chaque appel?
Autre chose que je devrais considérer?
Mise à jour: La première classe est opérationnelle avec la chaîne de responsabilité. Pour l'instant, j'ai choisi de ne pas utiliser le pattern de stratégie ou le repli pendant l'exécution de la méthode, car je pense que cela peut être inutile à la fin. Je pense que la plupart de ces solutions de repli seront meilleures en restant dans leurs propres classes, car il n'y aura pas de changement complet de plan de jeu, juste quelques modifications mineures à faire. Si cela s'avère ne pas être le cas, je sais au moins ce dont j'ai besoin d'enquêter maintenant.
Merci à tous ceux qui ont contribué à la solution ultime!
Pour les curieux, ma solution ultime travaillé à peu près comme ceci:
- Créer Handler classe abstraite, à peu près comme indiqué dans l'article de Wikipedia, mais avec une fonction
public abstract Handler GetHandler()
, et en ajoutant d'autres méthodes abstraites comme la charge, Enregistrer, etc. - Implémenter des sous-classes de gestionnaire privé pour la classe parente (elles pourraient aussi bien être des sous-classes, puisqu'elles ne traiteront que des choses pour cette classe particulière ... évite aussi les problèmes de nommage ultérieurs). Les classes enfants prennent toutes un paramètre du type de l'objet parent dans leur constructeur, ce qui leur permet d'accéder facilement aux données du parent.À partir du constructeur de la classe parente, configurez les gestionnaires/successeurs de la chaîne de responsabilité (encore une fois, comme dans l'exemple), puis appelez le
FirstHandler.GetHandler(this)
et stockez le résultat pour que la classe sache quel gestionnaire utiliser dans le futur. - La plupart des méthodes manipulées se réduisent simplement à.
Vous pouvez placer du code dans une liste numérotée en l'indentant avec _eight_ spaces. – SLaks
Merci pour le conseil de mise en page, qui me conduisait au mur! – RobinHood70