Menu
Coddy logo textTech

Patron Template Method

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy — leçon 94 sur 107.

Le patron Template Method définit le squelette d'un algorithme dans un type de base, permettant aux sous-types de redéfinir des étapes spécifiques sans modifier la structure globale. Alors que le Decorator ajoute du comportement en enveloppant des objets, Template Method contrôle le flux de l'algorithme et permet la personnalisation d'étapes individuelles.

En Go, comme il n'y a pas d'héritage, nous implémentons ce patron en utilisant l'imbrication de structures (struct embedding) combinée aux interfaces. La structure « template » définit la structure de l'algorithme et appelle des méthodes qui peuvent être personnalisées :

type DataProcessor interface {
    ReadData() string
    ProcessData(data string) string
    SaveData(result string) string
}

type BaseProcessor struct {
    Impl DataProcessor
}

func (b *BaseProcessor) Execute() string {
    data := b.Impl.ReadData()
    result := b.Impl.ProcessData(data)
    return b.Impl.SaveData(result)
}

Les implémentations concrètes fournissent leurs propres versions de chaque étape tandis que le flux de l'algorithme reste inchangé :

type CSVProcessor struct{}

func (c CSVProcessor) ReadData() string       { return "csv-data" }
func (c CSVProcessor) ProcessData(d string) string { return "processed-" + d }
func (c CSVProcessor) SaveData(r string) string    { return "Saved: " + r }

type JSONProcessor struct{}

func (j JSONProcessor) ReadData() string       { return "json-data" }
func (j JSONProcessor) ProcessData(d string) string { return "parsed-" + d }
func (j JSONProcessor) SaveData(r string) string    { return "Stored: " + r }

La méthode template Execute orchestre les étapes dans un ordre fixe :

csvProc := &BaseProcessor{Impl: CSVProcessor{}}
fmt.Println(csvProc.Execute())  // Enregistré : processed-csv-data

jsonProc := &BaseProcessor{Impl: JSONProcessor{}}
fmt.Println(jsonProc.Execute()) // Stocké : parsed-json-data

Le Template Method est idéal lorsque vous avez des algorithmes qui partagent la même structure mais diffèrent par des étapes spécifiques, tels que des pipelines d'importation/exportation de données, des générateurs de rapports ou des frameworks de test.

challenge icon

Défi

Facile

Construisons un système de génération de rapports en utilisant le patron de conception Template Method ! Vous allez créer un framework où différents types de rapports suivent le même processus de génération — collecte des données, formatage et sortie du résultat — mais chaque type de rapport personnalise ces étapes différemment.

Vous organiserez votre code sur trois fichiers :

  • report.go : Définissez votre interface et le processeur de base qui orchestre l'algorithme de génération de rapports.

    Créez une interface ReportGenerator avec trois méthodes qui représentent les étapes de la génération de rapports :

    • GatherData() string — récupère les données brutes pour le rapport
    • FormatData(data string) string — transforme les données dans le format du rapport
    • OutputReport(formatted string) string — produit le message de sortie final

    Construisez une structure ReportProcessor qui contient une implémentation de ReportGenerator. Ajoutez une méthode Generate() string qui exécute les trois étapes dans l'ordre : collecter, formater, puis sortir — en retournant le résultat final.

  • generators.go : Implémentez des générateurs de rapports concrets qui personnalisent chaque étape.

    Créez deux types de rapports :

    • SalesReport avec un champ Region (string)
      • GatherData() retourne "sales-data-" + la région
      • FormatData(data) retourne "SALES REPORT: " + les données
      • OutputReport(formatted) retourne "Printed: " + le contenu formaté
    • InventoryReport avec un champ Warehouse (string)
      • GatherData() retourne "inventory-" + l'entrepôt
      • FormatData(data) retourne "*** " + les données + " ***"
      • OutputReport(formatted) retourne "Exported: " + le contenu formaté
  • main.go : Démontrez comment la même structure d'algorithme produit des résultats différents selon l'implémentation.

    Lisez le type de rapport (sales ou inventory) et la valeur de configuration (région pour les ventes, entrepôt pour l'inventaire). Créez le générateur approprié, enveloppez-le dans un ReportProcessor, appelez Generate(), et affichez le résultat.

Les entrées suivantes seront fournies :

  • Ligne 1 : Type de rapport (sales ou inventory)
  • Ligne 2 : Valeur de configuration (nom de la région ou nom de l'entrepôt)

Par exemple, avec :

sales
North

Votre sortie devrait être :

Printed: SALES REPORT: sales-data-North

Et avec :

inventory
MainHub

Votre sortie devrait être :

Exported: *** inventory-MainHub ***

Et avec :

sales
West

Votre sortie devrait être :

Printed: SALES REPORT: sales-data-West

Remarquez comment le ReportProcessor appelle toujours les trois mêmes étapes dans le même ordre, mais chaque type de rapport fournit sa propre implémentation de ces étapes. Le squelette de l'algorithme reste fixe tandis que les détails varient — c'est le patron Template Method en action !

Aide-mémoire

Le patron de méthode (Template Method) définit le squelette d'un algorithme dans un type de base, permettant aux sous-types de surcharger des étapes spécifiques sans modifier la structure globale.

En Go, implémentez ce patron en utilisant l'imbrication de structures (struct embedding) combinée aux interfaces. La structure « template » définit la structure de l'algorithme et appelle des méthodes qui peuvent être personnalisées :

type DataProcessor interface {
    ReadData() string
    ProcessData(data string) string
    SaveData(result string) string
}

type BaseProcessor struct {
    Impl DataProcessor
}

func (b *BaseProcessor) Execute() string {
    data := b.Impl.ReadData()
    result := b.Impl.ProcessData(data)
    return b.Impl.SaveData(result)
}

Les implémentations concrètes fournissent leurs propres versions de chaque étape tandis que le flux de l'algorithme reste inchangé :

type CSVProcessor struct{}

func (c CSVProcessor) ReadData() string       { return "csv-data" }
func (c CSVProcessor) ProcessData(d string) string { return "processed-" + d }
func (c CSVProcessor) SaveData(r string) string    { return "Saved: " + r }

type JSONProcessor struct{}

func (j JSONProcessor) ReadData() string       { return "json-data" }
func (j JSONProcessor) ProcessData(d string) string { return "parsed-" + d }
func (j JSONProcessor) SaveData(r string) string    { return "Stored: " + r }

La méthode template orchestre les étapes dans un ordre fixe :

csvProc := &BaseProcessor{Impl: CSVProcessor{}}
fmt.Println(csvProc.Execute())  // Saved: processed-csv-data

jsonProc := &BaseProcessor{Impl: JSONProcessor{}}
fmt.Println(jsonProc.Execute()) // Stored: parsed-json-data

Le patron Template Method est idéal lorsque des algorithmes partagent la même structure mais diffèrent dans des étapes spécifiques, comme les pipelines d'importation/exportation de données, les générateurs de rapports ou les frameworks de test.

Essayez vous-même

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Lire le type de rapport
	scanner.Scan()
	reportType := scanner.Text()
	
	// Lire la valeur de configuration (région ou entrepôt)
	scanner.Scan()
	configValue := scanner.Text()

	// TODO: Créer le générateur approprié en fonction de reportType
	// - Si reportType est "sales", créer un SalesReport avec Region défini sur configValue
	// - Si reportType est "inventory", créer un InventoryReport avec Warehouse défini sur configValue
	
	// TODO: Créer un ReportProcessor avec le générateur
	
	// TODO: Appeler Generate() et afficher le résultat
	_ = reportType
	_ = configValue
	fmt.Println("TODO: Generate and print the report")
}
quiz iconTestez-vous

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