Template-Method-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 78 von 91.
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. Die Basisklasse steuert den Ablauf, während Unterklassen einzelne Teile anpassen.
Erwägen Sie die Erstellung verschiedener Arten von Dokumenten.
Jedes Dokument folgt demselben Prozess: Kopfzeile erstellen, Inhalt hinzufügen, Fußzeile erstellen. Aber die Besonderheiten jedes Schritts variieren je nach Dokumenttyp. Die Template-Methode definiert diese Sequenz, während Unterklassen die Details implementieren.
<?php
abstract class DocumentGenerator {
// Die Template-Methode - definiert die Struktur des Algorithmus
public final function generate(): string {
$output = $this->createHeader();
$output .= $this->createContent();
$output .= $this->createFooter();
return $output;
}
// Schritte, die von Unterklassen implementiert werden müssen
abstract protected function createHeader(): string;
abstract protected function createContent(): string;
abstract protected function createFooter(): string;
}
class HtmlDocument extends DocumentGenerator {
protected function createHeader(): string {
return "<html><head></head><body>";
}
protected function createContent(): string {
return "<p>Hello World</p>";
}
protected function createFooter(): string {
return "</body></html>";
}
}
class TextDocument extends DocumentGenerator {
protected function createHeader(): string {
return "=== DOCUMENT ===\n";
}
protected function createContent(): string {
return "Hello World\n";
}
protected function createFooter(): string {
return "=== END ===";
}
}
$html = new HtmlDocument();
echo $html->generate() . "\n";
$text = new TextDocument();
echo $text->generate();
Ausgabe:
<html><head></head><body><p>Hello World</p></body></html>
=== DOCUMENT ===
Hello World
=== END ===Beachten Sie das Schlüsselwort final bei der Template-Methode. Dies verhindert, dass Unterklassen die Struktur des Algorithmus ändern. Das Muster ist ideal, wenn Sie mehrere Klassen haben, die demselben Workflow folgen, sich aber in den Implementierungsdetails unterscheiden. Das Hinzufügen eines neuen Dokumenttyps bedeutet das Erstellen einer neuen Unterklasse, ohne den bestehenden Code zu berühren.
Aufgabe
EinfachLassen Sie uns ein Berichtserstellungssystem mit dem Template Method Pattern erstellen. Verschiedene Arten von Berichten folgen derselben Struktur — ein Titelabschnitt, ein Datenabschnitt und ein Zusammenfassungsabschnitt — aber jeder Berichtstyp formatiert diese Abschnitte unterschiedlich. Die Template-Methode wird diesen Workflow definieren, während Unterklassen jeden Schritt anpassen.
Sie werden Ihren Code über vier Dateien organisieren:
ReportGenerator.php— Erstellen Sie eine abstrakte KlasseReportGenerator, die das Skelett des Berichtserstellungsalgorithmus definiert. Ihre Klasse sollte:- Einen Berichtstitel in ihrem Konstruktor akzeptieren (verwenden Sie Constructor Promotion)
- Eine
finalöffentliche Methodegenerate(): stringhaben, die drei Schritte in der folgenden Reihenfolge aufruft:createTitle(),createBody()undcreateSummary(), und deren Ergebnisse verkettet - Drei abstrakte geschützte Methoden deklarieren, die Unterklassen implementieren müssen:
createTitle(): string,createBody(): stringundcreateSummary(): string
HtmlReport.php— Binden Sie die Datei ReportGenerator ein und erstellen Sie eine KlasseHtmlReport, die diese erweitert. Dieser Bericht formatiert die Ausgabe als HTML:createTitle()gibt"<h1>" . $this->title . "</h1>"zurückcreateBody()gibt"<p>Report data goes here</p>"zurückcreateSummary()gibt"<footer>End of report</footer>"zurück
PlainTextReport.php— Binden Sie die Datei ReportGenerator ein und erstellen Sie eine KlassePlainTextReport, die diese erweitert. Dieser Bericht verwendet eine einfache Textformatierung:createTitle()gibt"### " . $this->title . " ###\n"zurückcreateBody()gibt"Report data goes here\n"zurückcreateSummary()gibt"--- End of report ---"zurück
main.php— Binden Sie beide Berichtsdateien ein. Sie erhalten zwei Eingaben: einen Berichtstyp ("html"oder"text") und einen Berichtstitel.Erstellen Sie basierend auf dem Berichtstyp den entsprechenden Berichtsgenerator mit dem angegebenen Titel. Rufen Sie
generate()auf und geben Sie den vollständigen Bericht aus.
Das Template Method Pattern stellt sicher, dass alle Berichte derselben dreistufigen Struktur folgen, während es jedem Berichtstyp ermöglicht, seine Abschnitte individuell zu formatieren. Das Schlüsselwort final bei generate() verhindert, dass Unterklassen die Abfolge des Algorithmus ändern — sie können nur einzelne Schritte anpassen.
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 Schablonenmethode, die den Ablauf steuert. Diese Methode ist normalerweise als final markiert, um zu verhindern, dass Unterklassen die Struktur des Algorithmus verändern.
Unterklassen implementieren abstrakte Methoden, um einzelne Schritte des Algorithmus anzupassen.
<?php
abstract class DocumentGenerator {
// Schablonenmethode - definiert die Algorithmusstruktur
public final function generate(): string {
$output = $this->createHeader();
$output .= $this->createContent();
$output .= $this->createFooter();
return $output;
}
// Abstrakte Schritte, die von Unterklassen implementiert werden müssen
abstract protected function createHeader(): string;
abstract protected function createContent(): string;
abstract protected function createFooter(): string;
}
class HtmlDocument extends DocumentGenerator {
protected function createHeader(): string {
return "<html><head></head><body>";
}
protected function createContent(): string {
return "<p>Hello World</p>";
}
protected function createFooter(): string {
return "</body></html>";
}
}
$html = new HtmlDocument();
echo $html->generate();
Wesentliche Merkmale:
- Die Schablonenmethode ist als
finalmarkiert, um eine Änderung der Algorithmusstruktur zu verhindern - Abstrakte Methoden definieren Anpassungspunkte für Unterklassen
- Ideal, wenn mehrere Klassen demselben Workflow folgen, sich aber in den Implementierungsdetails unterscheiden
- Das Hinzufügen neuer Varianten erfordert lediglich das Erstellen neuer Unterklassen, ohne bestehenden Code zu ändern
Probier es selbst
<?php
require_once 'HtmlReport.php';
require_once 'PlainTextReport.php';
// Eingabe lesen
$reportType = trim(fgets(STDIN));
$reportTitle = trim(fgets(STDIN));
// TODO: Basierend auf dem Berichtstyp ("html" oder "text"),
// erstelle den entsprechenden Berichtsgenerator mit dem angegebenen Titel
// TODO: Rufe generate() auf und gib den vollständigen Bericht aus
?>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üsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem10Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungDependency InjectionAnonyme KlassenEnums (PHP 8.1)Fibers (PHP 8.1)Objekt-Klonen im DetailGeneratoren & Iteratoren13Entwurfsmuster Teil 2
Command-MusterAdapter-MusterDecorator-MusterTemplate-Method-MusterZustandsmusterComposite-MusterRepository-Muster2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung