Je travaille sur une application dont un module effectue successivement les opérations financières suivantes:
Lorsqu'un utilisateur demande qu'un certain montant soit transféré sur son compte bancaire:
Le résultat de toutes les actions ci-dessus doit être enregistré.
Si toutes les conditions ci-dessus sont remplies, la transaction est effectuée. À l'avenir, il pourrait y avoir des vérifications supplémentaires.
Quel modèle de conception orienté objet devrait être le mieux adapté au cas ci-dessus?
Cela ressemble à ce que vous recherchez est un Chaîne de responsabilité . Dans ce cas, vous pourriez avoir les classes suivantes:
TransactionValidatorBase
classe de base abstraiteTransactionTimeValidator
TransactionAmountValidator
TransactionAccountValidator
Ceux-ci sont enchaînés pour appliquer le nombre de règles que vous spécifiez.
Lecture plus poussée
Le modèle correct ici dépend vraiment d'un contexte. Avant de choisir un modèle particulier à respecter, j'essaierai de trouver des réponses à ces questions:
Basé sur une intuition, je les coderais comme des méthodes simples avec un paramètre d'agrégation pour les codes d'erreur.
public void DoTransaction(IErrorAgregator error, TransactionRequest request)
{
if(!IsTransactionInCertainTimePeriod(request, error)) return;
if(!IsTransactionAmountInUserBounds(request, error)) return;
if(!UserHaveDefaultAccount(request, error)) return;
bankingTransactor.PerformTransaction(request);
}
Ce pourrait être une bonne idée de mettre DoTransaction dans l'interface "ITransactionValidationStragegy" et de créer un super-type de couche qui contiendra le code passe-partout de validation.
Cependant, dans cette conception, je suppose que la logique de validation est déterminée au moment de la compilation.
Si votre séquence d'étapes fait principalement des tâches de validation (comme il vous semble), sans muter les entrées, je penserais en effet au modèle de "chaîne de responsabilité", comme expliqué dans sa réponse par @ p.s.w.g
Mais comme votre question est un peu plus générique, j'aimerais également ajouter le "traitement Pipeline", car avec celui-ci, une étape produirait une sortie qui deviendrait l'entrée pour l'étape suivante (mutant ainsi l'entrée d'origine) .
Voici deux articles à ce sujet:
Collection Pipeline par Martin Fowler
Discussion plus théorique sur le modèle
Bien que les modèles soient déjà mentionnés ici, je vous suggère de réfléchir à la façon dont vous souhaitez utiliser les mêmes dans votre application, en fonction des cadres que vous utilisez.
Par exemple, la validation que vous aimeriez faire, très probablement, continuera de changer au fur et à mesure que le temps avance (vous voudrez peut-être ajouter une nouvelle validation à l'avenir qui limite les transactions à 10 par jour). En outre, vous ne souhaiterez peut-être pas effectuer la validation avant que votre service commercial ou votre code d'intégration ne se déclenche. Ce serait bien si vous pouviez ajouter les validations en tant que validations configurables.
Si vous utilisez Struts, l'utilisation d'intercepteurs peut être une bonne idée. En cas de printemps, l'injection de haricots comme dépendance vous donne plus de souplesse. Ma suggestion est non seulement de regarder les modèles/idiomes, mais aussi de regarder le cadre que vous utilisez pour construire l'application et de voir comment vous pouvez mieux répondre à vos besoins d'un point de vue futuriste.