Bonnes pratiques
Design Pattern

Qu'est-ce que le pattern stratégie ?
Comment l'utiliser ?
Maxime nous partage ce qu'il a appris.


Partagé par Benoit GANTAUME
il y a presque 3 ans
3

Jonathan Laurent il y a presque 3 ans
Merci pour l'article ! Il est bien écrit et explique bien le pattern strategy.

Par contre, petite question, le comportent de NeSaitPasVoler affiche simplement un texte, mais que se passe-t-il dans un vrai cas ? Que fait on quand on lance réellement le vol d'un canard qui ne sait pas voler ?
Il tombe ? Il marche ? Il ne fait rien ? Cela provoque une erreur parce qu'on s'attendait à un canard qui vole ?

Merci pour les avis :)
Maxime Delporte il y a presque 3 ans
Bonjour Jonathan (excuse-moi d'avance si je me suis trompé entre ton nom et prénom, n'hésite pas à me corriger si c'est le cas, j'ai pris dans l'ordre Prénom Nom :D)
Merci pour ton retour !

Il faut voir l'interface ComportementAuVol comme le point de départ.
ComportementAuVol possède une méthode voler() qui permettra de réaliser tous les comportements souhaités pour tes canards :D

Je vais essayer de t'illustrer ça avec du code Swift.
Pour chacun des comportements souhaités, tu dois avoir une classe associée.
Par exemple, si tu souhaites qu'un canard vol, tu auras :

class CanardSachantVoler: ComportementAuVol {
func voler() {
// Ici il faudra mettre le code permettant à ton canard de voler
print("Je sais voler !")
}
}

Si tu souhaites que ton canard marche à la place de voler :

class CanardQuiMarche: ComportementAuVol {
func voler() {
// Ici il faudra mettre le code permettant à ton canard de marcher
print("Je ne vole pas mais je marche !")
}
}

Si tu souhaites que ton canard ne fasse rien :

class CanardNeSachantPasVoler: ComportementAuVol {
func voler() {
// Ici tu ne mets rien dans ta méthode et il ne se passera rien :)
print("Je ne fais rien !")
}
}

Une fois que tu as construis tes classes avec les différents comportements, tu peux instancier tes canards avec celles-ci :

// let est le mot clé pour une constante en Swift
let canardQuiMarche = Canard(comportementAuVol: CanardQuiMarche())
let canardQuiVol = Canard(comportementAuVol: CanardSachantVoler())

Une fois que c'est fait, lorsque tu appelleras voler, ça appellera le comportement avec lequel tu as instancié ton canard:

canardQuiMarche.voler();
canardQuiVol.voler();

Cela te donnera dans l'ordre en console:
"Je ne vole pas mais je marche !"
"Je sais voler !"

Les deux canards appellent la même méthode voler() ayant deux comportements différents définis lors de la création de l'objet :)

J'espère que mon exemple en Swift est compréhensible et que j'ai pu répondre à ta question :D
Si ça n'est pas le cas, n'hésite pas à me donner ton langage, si je le parle un peu j'essayerais de te refaire le même exemple avec celui-ci, ça te permettra de tester :)

Très bon week-end et encore merci pour ton retour :)
Jonathan Laurent il y a presque 3 ans
Merci beaucoup pour ton retour.
Enffait , j'ai bien compris l'exemple et le pattern strategy.
Je me demandais juste si on ne brisait pas le L de SOLID en implémentant une stratégie pour un canard qui ne sait pas voler.
Le comportement s'exprime sous forme d'un print ici, mais que se passerait-il si on avait une véritable implémentation.
c'est plus un problème de fond car la forme est bonne.
Bon week-end à toi et merci pour l'article
Jonathan Laurent il y a presque 3 ans
Et c'est bien Jonathan 😊
Romain Fallet il y a presque 3 ans - modifié il y a presque 3 ans
J’avoue que j’ai toujours eu du mal avec les exemples abstraits à base de canards, de voiture et autres simplification de ce genre. C’est tellement loin des concepts que je manipule au quotidien que ça ne résonne pas profondément en moi, même si je comprends en gros le principe évoqué. Je suis le seul dans ce cas ?
Benoit GANTAUME il y a presque 3 ans
Assez d'accord avec toi @Romain Fallet. La difficulté, c'est de trouver quelque chose qui soit assez parlant et dont la logique métier est assez simple...
Compromis pas évident.
As-tu déjà vu des articles qui y arrivent bien ?
Mathieu Barberot il y a presque 3 ans
Je ne sais pas si c'est plus parlant que les canards, mais on avait mis ça en place dans une mission sur un algo de calcul de tarif pour des assurances sur des prêts.
Selon l'option choisie (standard, capital restant dû ou in fine) on devait calculer le coût total de l'assurance pour ensuite l'échelonner sur la durée du prêt.
On avait donc un calcul du coût de l'assurance sous forme de stratégie qu'on pouvait alors passer à l'algo qui faisait le calcul total.

interface CoutAssuranceStrategy {
CoutAssurance calculCoutTotal(/* données du client et du prêt */);
}

class CoutAssuranceStandard implements CoutAssuranceStrategy { ... }
class CoutAssuranceCapitalRestantDu implements CoutAssuranceStrategy { ... }
class CoutAssuranceInFine implements CoutAssuranceStrategy { ... }

class Main {

Calculateur.montantRemboursementMensuel(
/* données du client et du prêt */
CoutAssuranceStrategyFactory.getStrategy(/* option choisie */)
// passage par une factory permettant de retourner la bonne implémentation en fonction de l'option, mais en gros ça fait un switch
)

}

Sinon, pour un exemple parlant, je trouve que celui de l'article Wikipedia en anglais avec la note d'un consommateur au bar en fonction de l'happy hour ou non est pas mal : en.wikipedia.org/...

Au final, je me demande s'il y a qqch que je n'ai pas saisi ou si c'est juste un mot savant pour dire qu'on utilise une interface avec plusieurs implémentations.
Benoit GANTAUME il y a presque 3 ans
"si c'est juste un mot savant pour dire qu'on utilise une interface avec plusieurs implémentations"
C'est pas tant un mot savant qu'une nomenclature...
Tu compresses de l'information derrière un nom qui devient non ambigü.
C'est toute la richesse d'un langage.
Romain Fallet il y a presque 3 ans
@Benoit GANTAUME j’ai pas d’exemple d’articles mais moi le concept que j’aime bien c’est celui des utilisateurs. Ça parle à tout le monde (je pense ?), un utilisateur peut être réduit à juste une adresse email si on veut un exemple méga simple, ou on peut en faire un méga-truc complexe avec de la persistence, des droits d’accès, de l’authentification... si on a besoin de matière pour illustrer un concept pointu
Romain Fallet il y a presque 3 ans
Ce commentaire a été supprimé par son auteur.
Pour ajouter un commentaire, tu dois te connecter ou créer un compte.
SCRUM et qualité de code avec Elodie Micoulet
Accéder à l'épisode
Trop de mock tue le test : ce que l'archi hexagonale a changé
Afficher la ressource
Réussir ton entretien de recrutement
Accéder à la vidéo
D'une architecture web MVC à une architecture Clean Hexagonale - Céline Gilet
Afficher la ressource
Le Paradoxe Du Code Legacy
Accéder à l'épisode
Artisan Développeur utilise des cookies afin de t'offrir les meilleurs services. En poursuivant ta navigation, tu acceptes l’utilisation de cookies. En savoir plus