Éditer sur GitHub

Strategy

Problème

Nous souhaitons pouvoir faire varier dynamiquement le comportement d'une partie d'un traitement.

Cas d'école

Prenons le cas d'une application de traitement d'image qui applique les trois étapes suivantes :

UML_DP_Strategy - initial

Nous l'exposons en ligne de commande sous la forme suivante :

traitement-image data/joconde.jpg data/joconde-blur.jpg

Voir mborne/pattern-strategy-ts - branche initial

Problème

Nous souhaitons faire évoluer l'application pour permettre le choix entre plusieurs opérations :

Nous ciblons pour cela l'ajout d'un paramètre à l'API en ligne de commande comme suit :

traitement-image {inputFile} {outputFile} (blur|greyscale)

Tentons différentes approches...

Pouvons nous nous appuyer sur un switch?

Nous pourrions nous contenter d'ajouter un paramètre à la méthode run et traiter les différents cas en fonction operationName :

UML_DP_Strategy - switch

Cette approche serait la plus simple mais elle possède plusieurs défauts :

Pouvons nous exploiter le polymorphisme?

Nous pourrions promouvoir Application en interface et nous appuyer sur le polymorphisme comme suit :

UML_DP_Strategy - heritage

Voir mborne/pattern-strategy-ts - branche heritage

A première vue, nous pourrions être satisfait d'une telle conception...

Problème : Que se passe-t'il si nous souhaitons maintenant pouvoir appliquer deux traitements successifs?

Nous avons soit :

Le problème de fond réside dans le fait que nous ne respectons pas plusieurs principes de conception :

Solution

Avec le patron Strategy, nous allons encapsuler le traitement dans un objet dont le seul rôle se limitera à appliquer le traitement (ImageProcessor) :

UML_DP_Strategy - strategy

Pour enchaîner les traitements (ex : blur,greyscale), nous pourrons par exemple exploiter le patron de conception Composite en modélisant une liste de traitement sous forme d'une ImageProcessorList.

Voir mborne/pattern-strategy-ts - branche strategy

Liens utiles