НЕ МОЛЧИ!!!    Сделай что-нибудь,
чтобы остановить войну России в Украине.
...бойтесь людей равнодушных - именно с их молчаливого согласия происходят все самые ужасные преступления на свете.   ("Репортаж с петлёй на шее")

Шаблон проектирования Template Method (Шаблонный метод)

Описывается поведенческий шаблон проектирования Template Method, условия его применения, приведен пример его реализации.

Содержание

  • Применение
  • Реализация
  • Итоги

Применение

Сегодня рассмотрим поведенческий шаблон проектирования Template Method. Шаблон позволяет в определенных случаях избежать дублирования кода. Когда же Template Method бывает полезен? Думаю, многие сталкивались с ситуацией, когда функционал приложения требовал весьма схожей обработки, но тем не менее не идентичной. Самое простое при этом дублировать во второй обработчик ранее созданный код и подправить его. Простое, но не лучшее решение. А если таких запросов не два и не три? А если в будущем поменяется существующая обработка?
Как раз в таких случаях вас выручит Template Method. Идея шаблона в том, чтобы в родительском классе алгоритм обработки разделить на общую неизменную часть и ту, что меняется. Общая часть обработки определяется в исходном классе, а изменяемая только декларируется и затем реализуется в наследниках. Как вариант, в родителе можно полностью определить обработку по умолчанию, разделив ее на части. Затем в наследниках переопределять изменяемую часть. За счет этого шаблон позволяет модифицировать часть алгоритма обработки в наследниках, сохраняя его общую структуру.

Реализация

В качестве примера реализации шаблона Template Method будем моделировать работу автомобиля. Вначале создадим родительский абстрактный класс, в котором определим общую часть методов моделирования и часть абстрактных методов, которые будут определены в наследниках. Кроме того, в родительском классе определим метод, определяющий общую структуру алгоритма моделирования.

abstract class AbstractCar
{
    //шаблонный метод определяет общий алгоритм
    public function templateMethod(): void
    {
        $this->start();
        $this->incSpeed();
        $this->decSpeed();
        $this->stop();
        $this->refill();
    }

    //определим совпадающие методы
    protected function start(): void
    {
        echo "Авто начало движение.";
    }

    protected function incSpeed(): void
    {
        echo "Авто увеличило скорость.";
    }

    protected function decSpeed(): void
    {
        echo "Авто уменьшило скорость.";
    }

    protected public function stop(): void
    {
        echo "Авто остановлено.";
    }

    // декларируем метод, который будет определен в наследниках 
    abstract protected function refill(): void;
}

В родительском классе метод templateMethod() определяет алгоритм моделирования автомобиля. Также приведены общие методы моделирования и задекларирован метод refill() заправки автомобиля. Последний будет определен в наследниках, т.к. разные типы автомобилей могут требовать специфической заправки.
Вот эти наследники.

class PetrolCar extends AbstractCar
{
    protected function refill(): void
    {
        echo "Заправка бензином";
    }
}
class ElectricCar extends AbstractCar
{
    protected function refill(): void
    {
        echo "Заправка аккумуляторных батарей";
    }
}

UML диаграмма созданных классов будет выглядеть так.

template method uml diagram

Таким образом, с помощью шаблона Template method мы расширили возможности моделирования для более широкого класса автомобилей без дублирования общего кода.

Итоги

Был рассмотрен поведенческий шаблон проектирования Template method. Вы узнали, что использование этого шаблона в схожих алгоритмах обработки зачастую позволяет избежать дублирования кода. Достигается это за счет разделения обработки на неизменяемые и изменяемые части в исходном абстрактном классе. В нем определяется неизменяемая часть, а изменяемая лишь декларируется и определяется в наследниках класса. Общая структура алгоритма при этом остается неизменной и контролируется исходным классом.

Перейти к списку шаблонов проектирования.