Schablonenmethodenmuster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 78 von 91.
Das Template-Method-Muster ist ein Verhaltensentwurfsmuster, das das Grundgerüst 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 Bestandteile anpassen.
Erwäge, verschiedene Arten von Dokumenten zu erstellen.
Jedes Dokument folgt demselben Ablauf: Kopfzeile erstellen, Inhalt hinzufügen, Fußzeile erstellen. Die Einzelheiten jedes Schritts unterscheiden sich jedoch je nach Dokumenttyp. Die Template-Methode definiert diese Reihenfolge, während Unterklassen die Details implementieren.
<?php
abstract class DocumentGenerator {
// Die Template-Methode - definiert die Algorithmusstruktur
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 ===Beachte das Schlüsselwort final bei der Template-Methode. Dadurch wird verhindert, dass Unterklassen die Struktur des Algorithmus ändern. Das Muster ist ideal, wenn du mehrere Klassen hast, die denselben Arbeitsablauf befolgen, sich aber in den Implementierungsdetails unterscheiden. Das Hinzufügen eines neuen Dokumenttyps bedeutet, eine neue Unterklasse zu erstellen, ohne vorhandenen Code anzufassen.
Aufgabe
EinfachErstellen wir ein System zur Berichtserstellung mit dem Template-Method-Muster. Verschiedene Berichtstypen folgen derselben Struktur – einem Titelabschnitt, einem Datenabschnitt und einem Zusammenfassungsabschnitt –, formatieren diese Abschnitte jedoch jeweils unterschiedlich. Die Template-Methode definiert diesen Ablauf, während Unterklassen jeden Schritt anpassen.
Du organisierst deinen Code über vier Dateien:
ReportGenerator.php: Erstelle eine abstrakte KlasseReportGenerator, die das Grundgerüst des Algorithmus zur Berichtserstellung definiert. Deine Klasse sollte:- einen Berichtstitel in ihrem Konstruktor akzeptieren (verwende Constructor Promotion)
- eine
finalöffentliche Methodegenerate(): stringbesitzen, die drei Schritte in dieser Reihenfolge aufruft:createTitle(),createBody()undcreateSummary(), und ihre Ergebnisse verkettet - drei abstrakte geschützte Methoden deklarieren, die Unterklassen implementieren müssen:
createTitle(): string,createBody(): stringundcreateSummary(): string
HtmlReport.php: Binde die Datei ReportGenerator ein und erstelle eine KlasseHtmlReport, die davon erbt. Dieser Bericht formatiert die Ausgabe als HTML:createTitle()gibt"<h1>[title]</h1>"zurückcreateBody()gibt"<p>Report data goes here</p>"zurückcreateSummary()gibt"<footer>End of report</footer>"zurück
PlainTextReport.php: Binde die Datei ReportGenerator ein und erstelle eine KlassePlainTextReport, die davon erbt. Dieser Bericht verwendet eine einfache Textformatierung:createTitle()gibt"### [title] ###\n"zurückcreateBody()gibt"Report data goes here\n"zurückcreateSummary()gibt"--- End of report ---"zurück
main.php: Binde beide Berichtsdateien ein. Du erhältst zwei Eingaben: einen Berichtstyp ("html"oder"text") und einen Berichtstitel.Erstelle abhängig vom Berichtstyp den passenden Berichtsgenerator mit dem angegebenen Titel. Rufe
generate()auf und gib den vollständigen Bericht aus.
Das Template-Method-Muster stellt sicher, dass alle Berichte derselben Struktur aus drei Schritten folgen, während jeder Berichtstyp seine Abschnitte auf eigene Weise formatieren kann. Das Schlüsselwort final bei generate() verhindert, dass Unterklassen die Reihenfolge des Algorithmus ändern. Sie können nur einzelne Schritte anpassen.
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 gegebenen Titel
// TODO: generate() aufrufen und den vollständigen Bericht ausgeben
?>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 OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen10Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungDependency InjectionAnonyme KlassenEnums (PHP 8.1)Fibers (PHP 8.1)Objektklonen im DetailGeneratoren & Iteratoren13Entwurfsmuster Teil 2
BefehlsmusterAdaptermusterDekorierermusterSchablonenmethodenmusterZustandsmusterKompositummusterRepository-Muster2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler