Patron Stratégie
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 93 sur 110.
Le patron de conception Stratégie (Strategy pattern) vous permet de définir une famille d'algorithmes, d'encapsuler chacun d'eux dans sa propre classe et de les rendre interchangeables au moment de l'exécution. Au lieu de coder le comportement en dur dans une classe, vous injectez le comportement via une interface, ce qui vous permet de changer de stratégie sans modifier la classe qui les utilise.
Considérez un système de paiement dans lequel vous souhaitez prendre en charge différents modes de paiement. Plutôt que d'utiliser des conditions pour gérer chaque méthode, vous définissez une interface de stratégie et créez des implémentations concrètes :
abstract class PaymentStrategy {
void pay(double amount);
}
class CreditCardPayment implements PaymentStrategy {
@override
void pay(double amount) => print('Paid \$amount with Credit Card');
}
class PayPalPayment implements PaymentStrategy {
@override
void pay(double amount) => print('Paid \$amount with PayPal');
}
class ShoppingCart {
PaymentStrategy _paymentStrategy;
ShoppingCart(this._paymentStrategy);
void setPaymentStrategy(PaymentStrategy strategy) {
_paymentStrategy = strategy;
}
void checkout(double total) {
_paymentStrategy.pay(total);
}
}
void main() {
var cart = ShoppingCart(CreditCardPayment());
cart.checkout(99.99); // Paid $99.99 with Credit Card
cart.setPaymentStrategy(PayPalPayment());
cart.checkout(49.99); // Paid $49.99 with PayPal
}Le ShoppingCart ne sait pas et ne se soucie pas de la manière dont le paiement fonctionne - il délègue simplement à la stratégie actuellement définie. Vous pouvez ajouter de nouveaux modes de paiement en créant de nouvelles classes de stratégie sans toucher au code du panier. Ce patron est idéal lorsque vous avez plusieurs façons d'effectuer une action et que vous souhaitez les sélectionner ou basculer entre elles de manière dynamique.
Défi
FacileConstruisons un système de formatage de texte en utilisant le pattern Strategy ! Vous allez créer un système où différentes stratégies de formatage peuvent être appliquées au texte, permettant aux utilisateurs de basculer entre les formats de manière dynamique sans modifier le processeur de texte principal.
Vous organiserez votre code en deux fichiers :
formatting_strategies.dart: Créez votre système de stratégie ici. Définissez une classe abstraiteFormattingStrategyavec une méthodeString format(String text). Ensuite, implémentez trois stratégies concrètes :UppercaseStrategy- convertit le texte en majusculesLowercaseStrategy- convertit le texte en minusculesTitleCaseStrategy- met en majuscule la première lettre de chaque mot (séparés par des espaces, première lettre de chaque mot en majuscule, le reste en minuscules)
TextProcessorqui contient uneFormattingStrategy. Elle doit avoir un constructeur qui accepte une stratégie initiale, une méthodesetStrategy()pour changer la stratégie au moment de l'exécution, et une méthodeprocess(String text)qui applique la stratégie actuelle et renvoie le résultat formaté.main.dart: Importez vos stratégies de formatage et démontrez comment le pattern Strategy permet un changement de comportement dynamique. Créez unTextProcessoren commençant par laUppercaseStrategy. Traitez le texte'hello world'et affichez le résultat. Ensuite, passez à laLowercaseStrategy, traitez'HELLO WORLD', et affichez le résultat. Enfin, passez à laTitleCaseStrategy, traitez'the quick brown fox', et affichez le résultat.
Cela démontre la puissance du pattern Strategy : votre TextProcessor n'a pas besoin de connaître les détails du fonctionnement du formatage. Il délègue simplement à la stratégie actuellement définie, ce qui facilite l'ajout de nouvelles options de formatage sans modifier le processeur !
Sortie attendue :
HELLO WORLD
hello world
The Quick Brown FoxAide-mémoire
Le pattern Strategy définit une famille d'algorithmes, encapsule chacun d'eux dans sa propre classe et les rend interchangeables au moment de l'exécution. Au lieu de coder le comportement en dur, vous l'injectez via une interface.
Définissez une interface de stratégie :
abstract class PaymentStrategy {
void pay(double amount);
}Créez des implémentations concrètes de la stratégie :
class CreditCardPayment implements PaymentStrategy {
@override
void pay(double amount) => print('Paid \$amount with Credit Card');
}
class PayPalPayment implements PaymentStrategy {
@override
void pay(double amount) => print('Paid \$amount with PayPal');
}Créez une classe de contexte qui utilise la stratégie :
class ShoppingCart {
PaymentStrategy _paymentStrategy;
ShoppingCart(this._paymentStrategy);
void setPaymentStrategy(PaymentStrategy strategy) {
_paymentStrategy = strategy;
}
void checkout(double total) {
_paymentStrategy.pay(total);
}
}Utilisez le pattern en injectant et en changeant de stratégie :
var cart = ShoppingCart(CreditCardPayment());
cart.checkout(99.99); // Paid $99.99 with Credit Card
cart.setPaymentStrategy(PayPalPayment());
cart.checkout(49.99); // Paid $49.99 with PayPalLa classe de contexte délègue le comportement à la stratégie sans connaître les détails d'implémentation. Ajoutez de nouvelles stratégies en créant de nouvelles classes sans modifier le code existant.
Essayez vous-même
import 'formatting_strategies.dart';
void main() {
// TODO: Créer un TextProcessor en commençant par UppercaseStrategy
// TODO: Traiter le texte 'hello world' et afficher le résultat
// TODO: Passer à LowercaseStrategy
// TODO: Traiter 'HELLO WORLD' et afficher le résultat
// TODO: Passer à TitleCaseStrategy
// TODO: Traiter 'the quick brown fox' et afficher le résultat
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository