Menu
Coddy logo textTech

Vorlagenmethodenmuster

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 59 von 70.

Das Template-Method-Muster ist ein Verhaltensmuster, das das Grundgerüst eines Algorithmus in einer Basisklasse definiert und Unterklassen ermöglicht, bestimmte Schritte zu überschreiben, ohne die Gesamtstruktur zu ändern. Die Basisklasse steuert den Ablauf, während abgeleitete Klassen einzelne Bestandteile anpassen.

Dieses Muster verwendet Vererbung und abstrakte Methoden. Die Basisklasse enthält eine „Vorlagenmethode“, die eine Abfolge von Schritten aufruft, von denen einige abstrakt sind und von Unterklassen implementiert werden müssen:

public abstract class DataProcessor
{
    // Template-Methode - definiert die Struktur des Algorithmus
    public void Process()
    {
        ReadData();
        ProcessData();
        SaveData();
    }
    
    protected abstract void ReadData();
    protected abstract void ProcessData();
    protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}

public class CsvProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading CSV file");
    protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}

public class JsonProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading JSON file");
    protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
    protected override void SaveData() => Console.WriteLine("Saving to cloud");
}

Jede Unterklasse stellt ihre eigene Implementierung bereit, während die Basisklasse die Reihenfolge der Operationen festlegt:

DataProcessor csv = new CsvProcessor();
csv.Process();
// CSV-Datei lesen
// CSV-Daten parsen
// Saving to default location

DataProcessor json = new JsonProcessor();
json.Process();
// JSON-Datei lesen
// JSON-Daten parsen
// In die Cloud speichern

Das Template-Method-Muster ist ideal, wenn mehrere Klassen dieselbe Algorithmusstruktur aufweisen, sich aber in bestimmten Schritten unterscheiden. Es fördert die Wiederverwendung von Code, indem die gemeinsame Logik in der Basisklasse platziert wird und gleichzeitig durch überschreibbare Methoden Flexibilität ermöglicht wird.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Berichtsgenerierungssystem mithilfe des Template-Method-Musters. Verschiedene Berichtstypen (z. B. Verkaufsberichte und Lagerbestandsberichte) haben dieselbe übergeordnete Struktur – sie müssen alle Daten sammeln, sie formatieren und das Ergebnis ausgeben –, aber jeder Berichtstyp verarbeitet diese Schritte unterschiedlich.

Du organisierst deinen Code auf drei Dateien verteilt:

  • ReportGenerator.cs: Erstelle eine abstrakte Klasse ReportGenerator im Namespace Reporting. Diese Basisklasse definiert das Grundgerüst des Algorithmus zur Berichtsgenerierung durch eine Template-Methode namens Generate(). Die Methode soll drei Schritte der Reihe nach aufrufen: GatherData(), FormatReport() und OutputReport(). Mache GatherData() und FormatReport() abstrakt (jeder Berichtstyp implementiert diese unterschiedlich), während OutputReport() eine virtuelle Methode mit einer Standardimplementierung sein soll, die Sending to default printer ausgibt.
  • ConcreteReports.cs: Erstelle zwei konkrete Berichtsklassen im selben Namespace, die von ReportGenerator erben:
    • SalesReport – implementiert GatherData(), um Collecting sales data from database auszugeben, und FormatReport(), um Formatting as sales summary auszugeben
    • InventoryReport – implementiert GatherData(), um Scanning warehouse inventory auszugeben, FormatReport(), um Formatting as inventory list auszugeben, und überschreibt OutputReport(), um Sending to warehouse manager auszugeben
  • Program.cs: Führe alles zusammen, indem du Berichtinstanzen erstellst und sie generierst. Die Template-Methode stellt sicher, dass jeder Bericht denselben dreistufigen Prozess durchläuft, aber das konkrete Verhalten jedes Schritts variiert je nach Berichtstyp.

Du erhältst eine Eingabe:

  • Der Berichtstyp: sales oder inventory

Erstelle anhand der Eingabe den passenden Berichtsgenerator und rufe seine Methode Generate() auf.

Wenn die Eingabe beispielsweise sales lautet, sollte die Ausgabe wie folgt aussehen:

Collecting sales data from database
Formatting as sales summary
Sending to default printer

Wenn die Eingabe inventory lautet, sollte die Ausgabe wie folgt aussehen:

Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse manager

Beachte, dass beide Berichte exakt derselben Algorithmusstruktur folgen (sammeln, formatieren, ausgeben), die Implementierung jedes Schritts jedoch angepasst ist. SalesReport verwendet das standardmäßige Ausgabeverhalten, während InventoryReport es überschreibt – damit wird veranschaulicht, wie du mit dem Template-Method-Muster festlegen kannst, welche Schritte zwingend überschrieben werden müssen und welche optional angepasst werden können!

Probier es selbst

using System;
using Reporting;

class Program
{
    public static void Main(string[] args)
    {
        string reportType = Console.ReadLine();
        
        // TODO: Erstelle den entsprechenden Berichtsgenerator basierend auf reportType
        // Wenn reportType "sales" ist, erstelle einen SalesReport
        // Wenn reportType "inventory" ist, erstelle einen InventoryReport
        // Rufe dann die Generate()-Methode auf dem Bericht auf
        
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C#-Compiler