Паттерн «Шаблонный метод»
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 78 из 91.
Template Method Pattern — это поведенческий шаблон проектирования, который определяет каркас алгоритма в базовом class, позволяя подклассам переопределять отдельные шаги без изменения общей структуры. Базовый class управляет рабочим процессом, а подклассы настраивают отдельные части.
Рассмотрите создание разных типов документов.
Каждый документ следует одному и тому же процессу: create заголовок, добавить содержимое, create нижний колонтитул. Но конкретные детали каждого шага различаются в зависимости от типа документа. Шаблонный method определяет эту последовательность, а подклассы implement детали.
<?php
abstract class DocumentGenerator {
// Шаблонный метод — определяет структуру алгоритма
public final function generate(): string {
$output = $this->createHeader();
$output .= $this->createContent();
$output .= $this->createFooter();
return $output;
}
// Шаги, которые должны быть реализованы подклассами
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();
Вывод:
<html><head></head><body><p>Hello World</p></body></html>
=== DOCUMENT ===
Hello World
=== END ===Обратите внимание на ключевое слово final в шаблонном методе. Это не позволяет подклассам изменять структуру алгоритма. Паттерн идеально подходит, когда у вас есть несколько классов, которые следуют одному и тому же рабочему процессу, но отличаются деталями реализации. Добавление нового типа документа означает создание нового подкласса без изменения существующего кода.
Задание
ЛегкоДавайте создадим систему генерации отчетов с использованием паттерна «Шаблонный метод». Разные типы отчетов следуют одной и той же структуре: раздел заголовка, раздел данных и раздел сводки, но каждый тип отчета форматирует эти разделы по-своему. Шаблонный метод определит этот рабочий процесс, а подклассы настроят каждый шаг.
Вы организуете код в четырех файлах:
ReportGenerator.php: Создайте abstractReportGeneratorclass, который определяет каркас algorithm генерации отчета. Ваш class должен:- Принимать заголовок отчета в своем constructor (используйте продвижение свойств constructor)
- Иметь
finalpublic methodgenerate(): string, который вызывает три шага в следующем order:createTitle(),createBody()иcreateSummary(), объединяя их результаты - Declare три abstract protected method, которые подклассы должны implement:
createTitle(): string,createBody(): stringиcreateSummary(): string
HtmlReport.php: Подключите файл ReportGenerator и создайтеHtmlReportclass, который extends его. Этот отчет форматирует output как HTML:createTitle()возвращает"<h1>[title]</h1>"createBody()возвращает"<p>Report data goes here</p>"createSummary()возвращает"<footer>End of report</footer>"
PlainTextReport.php: Подключите файл ReportGenerator и создайтеPlainTextReportclass, который extends его. Этот отчет использует простое текстовое форматирование:createTitle()возвращает"### [title] ###\n"createBody()возвращает"Report data goes here\n"createSummary()возвращает"--- End of report ---"
main.php: Подключите оба файла отчетов. Вы получите два входных значения: тип отчета ("html"или"text") и заголовок отчета.На основе типа отчета создайте appropriate report generator с given заголовком. Вызовите
generate()и выведите complete отчет.
Паттерн «Шаблонный метод» гарантирует, что все отчеты следуют одной и той же трехэтапной структуре, позволяя каждому типу отчета уникальным образом форматировать свои разделы. Ключевое слово final у generate() не позволяет подклассам изменять последовательность algorithm. Они могут настраивать только отдельные шаги.
Попробуйте сами
<?php
require_once 'HtmlReport.php';
require_once 'PlainTextReport.php';
// Прочитать ввод
$reportType = trim(fgets(STDIN));
$reportTitle = trim(fgets(STDIN));
// TODO: На основе типа отчёта ("html" или "text"),
// создайте соответствующий генератор отчёта с заданным заголовком
// TODO: Вызовите generate() и выведите полный отчёт
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Повторение — простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыПовторение — иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateМодификаторы доступа подробноГеттеры и сеттерыСокрытие информацииПродвижение конструктора (8.0)Повторение — система учёта студентов10Продвинутые концепции ООП
Композиция и наследованиеВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Репозиторий»2Пространства имён и автозагрузка
Введение в пространства имёнКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerПовторение — структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс и абстрактный классАннотация типов с интерфейсамиПовторение — калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeПовторение — пользовательская коллекция3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищённые свойстваСвойства только для чтения (PHP 8.1)Повторение — менеджер банковского счёта6Полиморфизм
Повторение переопределения методовПолиморфизм через интерфейсыАннотации типов и объединённые типыПозднее статическое связываниеПовторение — обработчик платежей9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования, часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн StrategyПотренируйтесь самостоятельно: Онлайн-компилятор PHP