Template-Method-Muster
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 73 von 87.
Das Template-Method-Pattern 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. Stellen Sie es sich wie ein Rezept vor: Der allgemeine Kochvorgang bleibt gleich, aber einzelne Zutaten oder Techniken können variieren.
Das Muster verwendet eine abstrakte Klasse mit einer Template-Methode, die eine Abfolge von Schritten aufruft. Einige Schritte besitzen Standardimplementierungen, während andere abstrakt sind und von Unterklassen implementiert werden müssen:
abstract class DataProcessor {
// Template-Methode - definiert die Algorithmusstruktur
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Standardimplementierung (Hook-Methode)
void saveData() {
System.out.println("Saving to default location");
}
}
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}
class XMLProcessor extends DataProcessor {
void readData() {
System.out.println("Reading XML file");
}
void processData() {
System.out.println("Parsing XML data");
}
}Die Template-Methode wird normalerweise als final markiert, um zu verhindern, dass Unterklassen die Struktur des Algorithmus ändern. Wenn sie aufgerufen wird, führt sie für alle Unterklassen dieselbe Sequenz aus:
DataProcessor csv = new CSVProcessor();
csv.process();
// Ausgabe:
// CSV-Datei wird gelesen
// CSV-Daten werden geparst
// Speichern am StandardspeicherortDas Template-Method-Pattern ist ideal, wenn Sie Algorithmen haben, die dieselbe Struktur teilen, sich aber in spezifischen Schritten unterscheiden. Es fördert die Wiederverwendung von Code, indem es die gemeinsame Logik in der Basisklasse platziert, während Anpassungen durch Vererbung ermöglicht werden.
Aufgabe
EinfachLassen Sie uns ein Dokumentenerstellungssystem mit dem Template Method Pattern erstellen! Sie werden ein Framework entwickeln, in dem verschiedene Dokumenttypen (Berichte und Rechnungen) demselben Erstellungsprozess folgen, aber spezifische Schritte anpassen. Dies ist ideal für Szenarien, in denen der gesamte Workflow festgelegt ist, die Details jedoch je nach Dokumenttyp variieren.
Sie werden Ihren Code in vier Dateien organisieren:
DocumentGenerator.java: Erstellen Sie die abstrakte Basisklasse, die die Template-Methode definiert. IhrDocumentGeneratorsollte Folgendes enthalten:Eine
finalMethode namensgenerateDocument(), die das Algorithmus-Skelett definiert, indem sie drei Schritte nacheinander aufruft:createHeader(),createBody()undcreateFooter().Zwei abstrakte Methoden:
createHeader()undcreateBody(), die von Unterklassen implementiert werden müssen.Eine Hook-Methode
createFooter()mit einer Standardimplementierung, die--- End of Document ---ausgibt.ReportGenerator.java: Erstellen Sie eine konkrete Unterklasse zum Generieren von Berichten. Sie sollte einen Berichtstitel (String) über ihren Konstruktor entgegennehmen.Die Methode
createHeader()gibt=== REPORT: [title] ===aus.Die Methode
createBody()gibtReport content goes here...aus.Verwenden Sie den geerbten Standard-Footer.
InvoiceGenerator.java: Erstellen Sie eine weitere konkrete Unterklasse zum Generieren von Rechnungen. Sie sollte einen Kundennamen (String) und einen Betrag (double) über ihren Konstruktor entgegennehmen.Die Methode
createHeader()gibt*** INVOICE ***aus.Die Methode
createBody()gibtCustomer: [name]in einer Zeile aus, gefolgt vonAmount Due: $[amount]in der nächsten Zeile (formatieren Sie den Betrag auf zwei Dezimalstellen).Überschreiben Sie
createFooter(), umThank you for your business!auszugeben.Main.java: Führen Sie Ihr Template-Methoden-System zusammen! Sie erhalten drei Eingaben: einen Berichtstitel (String), einen Kundennamen (String) und einen Rechnungsbetrag (double).Erstellen Sie einen
ReportGeneratormit dem Titel und rufen SiegenerateDocument()auf. Geben Sie eine Leerzeile zur Trennung aus. Erstellen Sie dann einenInvoiceGeneratormit dem Kundennamen und dem Betrag und rufen SiegenerateDocument()auf.
Sie erhalten drei Eingaben in der folgenden Reihenfolge: Berichtstitel (String), Kundenname (String) und Rechnungsbetrag (double).
Zum Beispiel, mit den Eingaben Q4 Sales, Acme Corp und 1500.00, wäre Ihre Ausgabe:
=== REPORT: Q4 Sales ===
Report content goes here...
--- End of Document ---
*** INVOICE ***
Customer: Acme Corp
Amount Due: $1500.00
Thank you for your business!Beachten Sie, wie beide Dokumenttypen demselben dreistufigen Prozess folgen, der in der Template-Methode definiert ist, aber jeder die Schritte unterschiedlich anpasst. Der ReportGenerator verwendet den Standard-Footer, während der InvoiceGenerator seinen eigenen bereitstellt – das ist die Stärke von Hook-Methoden im Template Method Pattern!
Spickzettel
Das Template Method Pattern (Schablonenmethode) 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.
Das Muster verwendet eine abstrakte Klasse mit einer Schablonenmethode, die eine Abfolge von Schritten aufruft. Einige Schritte verfügen über Standardimplementierungen, während andere abstrakt sind und von Unterklassen implementiert werden müssen:
abstract class DataProcessor {
// Schablonenmethode - definiert die Struktur des Algorithmus
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Standardimplementierung (Hook-Methode)
void saveData() {
System.out.println("Saving to default location");
}
}Konkrete Unterklassen implementieren die abstrakten Methoden:
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}Die Schablonenmethode ist als final markiert, um zu verhindern, dass Unterklassen die Struktur des Algorithmus ändern. Wenn sie aufgerufen wird, führt sie für alle Unterklassen dieselbe Sequenz aus:
DataProcessor csv = new CSVProcessor();
csv.process();
// Ausgabe:
// Reading CSV file
// Parsing CSV data
// Saving to default locationHauptmerkmale:
- Die Schablonenmethode ist
finalund definiert die Struktur des Algorithmus - Abstrakte Methoden müssen von Unterklassen implementiert werden
- Hook-Methoden bieten Standardimplementierungen, die optional überschrieben werden können
- Fördert die Wiederverwendung von Code, indem gemeinsame Logik in der Basisklasse platziert wird
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String reportTitle = scanner.nextLine();
String customerName = scanner.nextLine();
double invoiceAmount = scanner.nextDouble();
// TODO: Erstelle einen ReportGenerator mit dem Titel und rufe generateDocument() auf
// TODO: Gib eine Leerzeile zur Trennung aus
// TODO: Erstelle einen InvoiceGenerator mit dem Kundennamen und dem Betrag und rufe generateDocument() 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 DateienEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenFelder (Attribute)Konstruktor-MethodeKonstruktor-ÜberladungRückblick – Einfacher Taschenrechner4Vererbung
Grundlagen der Vererbung (extends)Das super-SchlüsselwortMethoden überschreiben (@Override)Konstruktor-VerkettungDie Object-KlasseEinfache & mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-InterfaceZusammenfassung – Benutzerdefiniertes Sortieren2Zugriffsmodifikatoren & Kapselung
Überblick über ZugriffsebenenGetter- und Setter-MethodenInformation HidingDas final-SchlüsselwortRückblick – Bankkonto-Manager5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenZusammenfassung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, geschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Teil 1
Einführung in Design PatternsSingleton-PatternFactory-PatternBuilder-PatternObserver-PatternStrategy-Pattern14Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung3Klasseneigenschaften & Statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Zusammenfassung – Zähler & Utility6Interfaces & Abstrakte Klassen
Einführung in InterfacesInterfaces implementierenImplementierung mehrerer InterfacesDefault- & statische Methoden in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesZusammenfassung - Zahlungssystem9Generics
Einführung in GenericsGenerische KlassenGenerische MethodenEingeschränkte TypparameterWildcards (?, extends, super)Zusammenfassung – Generische Container12Entwurfsmuster Teil 2
Command-MusterAdapter-MusterDecorator-MusterTemplate-Method-MusterState-MusterComposite-MusterIterator-Muster