Template-Method-Muster
Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy — Lektion 59 von 70.
Das Template-Method-Muster ist ein Verhaltensmuster, das das Skelett eines Algorithmus in einer Basisklasse definiert und es Unterklassen ermöglicht, bestimmte Schritte zu überschreiben, ohne die Gesamtstruktur zu ändern. Die Basisklasse steuert den Ablauf, während abgeleitete Klassen einzelne Teile anpassen.
Dieses Muster verwendet Vererbung und abstrakte Methoden. Die Basisklasse enthält eine „Template-Methode“, 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 erzwingt:
DataProcessor csv = new CsvProcessor();
csv.Process();
// CSV-Datei lesen
// CSV-Daten parsen
// Am Standardspeicherort speichern
DataProcessor json = new JsonProcessor();
json.Process();
// JSON-Datei lesen
// JSON-Daten parsen
// In der Cloud speichernDas Template-Method-Muster ist ideal, wenn mehrere Klassen dieselbe Algorithmusstruktur teilen, sich aber in spezifischen Schritten unterscheiden. Es fördert die Wiederverwendung von Code, indem es die gemeinsame Logik in der Basisklasse platziert und gleichzeitig Flexibilität durch überschreibbare Methoden ermöglicht.
Aufgabe
EinfachLassen Sie uns ein Berichtserstellungssystem mit dem Template Method Pattern erstellen. Verschiedene Arten von Berichten (wie Verkaufsberichte und Inventarberichte) teilen die gleiche Gesamtstruktur – sie müssen alle Daten sammeln, formatieren und das Ergebnis ausgeben – aber jeder Berichtstyp verarbeitet diese Schritte unterschiedlich.
Sie werden Ihren Code über drei Dateien organisieren:
ReportGenerator.cs: Erstellen Sie eine abstrakte KlasseReportGeneratorim NamespaceReporting. Diese Basisklasse definiert das Skelett des Berichtserstellungsalgorithmus durch eine Template-Methode namensGenerate(). Die Methode sollte drei Schritte nacheinander aufrufen:GatherData(),FormatReport()undOutputReport(). Machen SieGatherData()undFormatReport()abstrakt (jeder Berichtstyp wird diese unterschiedlich implementieren), währendOutputReport()eine virtuelle Methode mit einer Standardimplementierung sein sollte, dieSending to default printerausgibt.ConcreteReports.cs: Erstellen Sie zwei konkrete Berichtsklassen im selben Namespace, die vonReportGeneratorerben:SalesReport– implementiertGatherData(), umCollecting sales data from databaseauszugeben, undFormatReport(), umFormatting as sales summaryauszugeben.InventoryReport– implementiertGatherData(), umScanning warehouse inventoryauszugeben,FormatReport(), umFormatting as inventory listauszugeben, und überschreibtOutputReport(), umSending to warehouse managerauszugeben.
Program.cs: Führen Sie alles zusammen, indem Sie Berichtsinstanzen erstellen und diese generieren. Die Template-Methode stellt sicher, dass jeder Bericht demselben dreistufigen Prozess folgt, aber das spezifische Verhalten jedes Schritts variiert je nach Berichtstyp.
Sie erhalten eine Eingabe:
- Den Berichtstyp:
salesoderinventory
Erstellen Sie den entsprechenden Berichtsgenerator basierend auf der Eingabe und rufen Sie dessen Methode Generate() auf.
Wenn die Eingabe beispielsweise sales ist, sollte die Ausgabe wie folgt aussehen:
Collecting sales data from database
Formatting as sales summary
Sending to default printerWenn die Eingabe inventory ist, sollte die Ausgabe wie folgt aussehen:
Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse managerBeachten Sie, wie beide Berichte genau derselben Algorithmusstruktur folgen (Sammeln, Formatieren, Ausgeben), aber die Implementierung jedes Schritts angepasst ist. Der SalesReport verwendet das Standard-Ausgabeverhalten, während InventoryReport es überschreibt – dies zeigt, wie das Template Method Pattern es Ihnen ermöglicht zu steuern, welche Schritte zwingend überschrieben werden müssen und welche optional angepasst werden können!
Spickzettel
Das Template Method Pattern (Schablonenmethode) definiert das Skelett eines Algorithmus in einer Basisklasse und ermöglicht es Unterklassen, bestimmte Schritte zu überschreiben, ohne die Gesamtstruktur zu ändern.
Die Basisklasse enthält eine „Template-Methode“, die eine Abfolge von Schritten aufruft. Einige Schritte sind abstrakt (müssen von Unterklassen implementiert werden), während andere virtuell sein können (optional zu überschreiben):
public abstract class DataProcessor
{
// Template-Methode - definiert die Algorithmusstruktur
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected abstract void ProcessData();
protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}Unterklassen stellen ihre eigenen Implementierungen bereit, während die Basisklasse die Reihenfolge der Operationen erzwingt:
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");
}Verwendung:
DataProcessor csv = new CsvProcessor();
csv.Process();
// Reading CSV file
// Parsing CSV data
// Saving to default location
DataProcessor json = new JsonProcessor();
json.Process();
// Reading JSON file
// Parsing JSON data
// Saving to cloudDas Template Method Pattern ist ideal, wenn mehrere Klassen dieselbe Algorithmusstruktur teilen, sich aber in bestimmten Schritten unterscheiden. Es fördert die Wiederverwendung von Code, indem es die gemeinsame Logik in der Basisklasse platziert und gleichzeitig Flexibilität durch überschreibbare Methoden ermöglicht.
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 Methode Generate() für den Bericht auf
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienNamespaces & DirektivenEinführung in Klassen & ObjekteDas 'this'-SchlüsselwortMethoden und ParameterFelder vs. EigenschaftenKonstruktorenObjekt-InitialisiererZusammenfassung - Einfacher Taschenrechner4Vererbung
Grundlagen der Vererbung (:) SyntaxDas 'base'-SchlüsselwortVirtual & Override SchlüsselwörterVersiegelte KlassenDie 'object'-BasisklasseZusammenfassung – Mitarbeiter-Hierarchie7Fortgeschrittene Funktionen
OperatorüberladungIndexer (this[])ToString() überschreibenErweiterungsmethodenZusammenfassung - Benutzerdefinierte Liste2Eigenschaften & Statische Member
Automatisch implementierte EigenschaftenRead-Only- & Write-Only-EigenschaftenStatische Felder & MethodenStatische KlassenExpression-Bodied Member5Polymorphismus & Interfaces
Compile- vs. Runtime-PolymorphismusInterface vs. abstrakte KlasseMehrfache InterfacesExplizite InterfacesUpcasting & DowncastingRecap – Shape Calculator8Fortgeschrittene OOP-Konzepte
Komposition statt VererbungGenerics (Klassen & Methoden)Delegates und EventsAttribute und ReflectionIDisposable & using-AnweisungDependency Injection Grundlagen11Entwurfsmuster Teil 2
Command-MusterAdapter-MusterDecorator-MusterTemplate-Method-MusterZustandsmusterKompositum-Muster3Klassenarchitektur
Instanz- vs. statische Daten'readonly' & 'const' SchlüsselwörterBacking FieldsZusammenfassung - Bankkonto-Manager6Kapselung
ZugriffsmodifikatorenProperties zur KapselungImplementierung von Data HidingImmutability-MusterRückblick – Studierendendaten