Patron Méthode modèle
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy. Leçon 97 sur 110.
Le patron Template Method définit le squelette d’un algorithme dans une classe de base, permettant aux sous-classes de remplacer des étapes spécifiques sans modifier la structure globale. La classe de base contrôle le flux de travail, tandis que les sous-classes personnalisent les étapes individuelles.
Ce modèle utilise l’héritage : une classe abstraite définit une méthode modèle qui appelle une séquence d’étapes, dont certaines sont abstraites (elles doivent être implémentées par les sous-classes) et dont certaines disposent d’implémentations par défaut :
abstract class DataProcessor {
// Méthode template - définit la structure de l'algorithme
void process() {
readData();
processData();
saveData();
}
void readData(); // Abstrait - les sous-classes doivent implémenter
void processData(); // Abstrait - les sous-classes doivent implémenter
void saveData() { // Implémentation par défaut
print('Data saved to database');
}
}
class CsvProcessor extends DataProcessor {
@override
void readData() => print('Reading CSV file');
@override
void processData() => print('Parsing CSV rows');
}
class JsonProcessor extends DataProcessor {
@override
void readData() => print('Reading JSON file');
@override
void processData() => print('Parsing JSON objects');
@override
void saveData() => print('Saved to cloud storage');
}
void main() {
var csv = CsvProcessor();
csv.process();
// Lecture du fichier CSV
// Analyse des lignes CSV
// Données enregistrées dans la base de données
var json = JsonProcessor();
json.process();
// Lecture du fichier JSON
// Analyse des objets JSON
// Enregistré dans le stockage cloud
}La méthode process() est le modèle : elle définit l’ordre des opérations. Les sous-classes implémentent readData() et processData() différemment, et peuvent éventuellement redéfinir saveData(). L’avantage principal est que la structure de l’algorithme reste cohérente dans toutes les implémentations, tout en permettant une certaine flexibilité dans les étapes individuelles.
Défi
FacileConstruisons un système de génération de rapports en utilisant le patron Template Method ! Vous allez créer un framework dans lequel différents types de rapports suivent la même structure générale, mais où chaque type de rapport personnalise certaines étapes, comme la collecte des données et la mise en forme du résultat.
Vous allez organiser votre code en deux fichiers :
report_generator.dart: ce fichier contient votre classe de base abstraite et les implémentations concrètes des rapports. Créez une classe de base abstraiteReportGeneratoravec une méthode modèle appeléegenerate()qui définit le workflow de génération du rapport dans cet ordre :fetchData(),analyzeData(),formatReport()etdeliver(). Les méthodesfetchData()etformatReport()doivent être abstraites (chaque type de rapport les gère différemment), tandis queanalyzeData()doit afficherAnalyzing data...etdeliver()doit afficherReport delivered via email.en tant qu’implémentations par défaut. Créez ensuite deux classes concrètes de rapports :SalesReport- sa méthodefetchData()afficheFetching sales data from database...et sa méthodeformatReport()afficheFormatting as bar charts and tables.InventoryReport- sa méthodefetchData()afficheFetching inventory levels from warehouse..., sa méthodeformatReport()afficheFormatting as inventory list., et elle remplacedeliver()pour afficherReport sent to warehouse manager.
main.dart: importez votre fichier de génération de rapports et montrez comment le patron Template Method conserve une structure d’algorithme cohérente tout en permettant la personnalisation. Créez unSalesReportet appelez sa méthodegenerate(). Affichez ensuite une ligne vide pour séparer les résultats. Créez unInventoryReportet appelez également sa méthodegenerate().
Remarquez que les deux rapports suivent le même processus en quatre étapes, mais que chacun personnalise les étapes importantes pour son objectif spécifique. L’InventoryReport remplace même la méthode de livraison par défaut afin d’envoyer les rapports à un autre destinataire !
Résultat attendu :
Fetching sales data from database...
Analyzing data...
Formatting as bar charts and tables.
Report delivered via email.
Fetching inventory levels from warehouse...
Analyzing data...
Formatting as inventory list.
Report sent to warehouse manager.Essayez vous-même
import 'report_generator.dart';
void main() {
// TODO: Créer un SalesReport et appeler sa méthode generate()
// TODO: Afficher une ligne vide pour la séparation
// TODO: Créer un InventoryReport et appeler sa méthode generate()
}
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
1Fondamentaux de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs objetsLe mot-clé thisMéthodesVariables d’instanceBases des constructeursRécapitulatif - Calculatrice simple4Sécurité face aux valeurs nulles
Introduction à la sécurité face aux valeurs nullesNullable vs Non-NullableLes opérateurs ? et !Mot-clé Late et sécurité face aux valeurs nullesOpérateurs sensibles à nullSécurité face aux valeurs nulles dans les classesRécapitulatif – Système de profil utilisateur7Classes abstraites et interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémenter ou étendreInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et génériques
Vue d’ensemble des List, Set et MapCollections à typage sûrClasses génériquesMéthodes génériquesContraintes génériquesIterable et IteratorRécapitulatif – stockage générique2Constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs redirigésRécapitulatif - Constructeur de formes5Encapsulation
Membres publics vs privésLa convention du préfixe _Confidentialité au niveau de la bibliothèqueApprofondissement des getters et settersMasquage de l’informationRécapitulatif - Fiches des étudiants8Mixins
Introduction aux MixinsCréer des MixinsUtiliser plusieurs MixinsMot-clé on dans les MixinsMixin ou héritageMixin ou interfaceRécapitulatif - Système animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode et ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy3Propriétés des classes
Membres d’instance et statiquesChamps Final et ConstVariables différéesMéthodes et champs statiquesAccesseurs et mutateursRécapitulatif - Gestionnaire de compte bancaire6Héritage
Héritage de baseLe mot-clé superRedéfinition de méthodeL’annotation @overrideLe mot-clé de classe finalConstructeurs et héritageRécapitulatif – Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification des types à l’exécutionLes opérateurs is et asMot-clé covariantRécapitulatif - Processeur de paiements12POO asynchrone
Futures et async/awaitNotions de base des StreamsContrôleurs de StreamsConstructeurs asynchronesAsynchrone dans les méthodes de classeRécapitulatif - récupérateur de données15Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron DépôtEntraînez-vous par vous-même : Compilateur Dart en ligne