Template Method

Назначение

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

  • требуется получить базовый метод, позволив переопределять его части конкретным подклассам;
  • можно упростить класс для реализации функционала через наследование, предоставив шаблон класса, в котором оставлены “пробелы”, которые необходимо заполнить;
  • необходимо централизовать функциональность метода, которая остается единой для всех подклассов, но в каждом подклассе она может выполняться по-своему.

Описание

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

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

Реализация

Абстрактный класс определяет конкретный шаблонный метод, который вызывает одну или несколько абстрактных операций (как правило, protected). Конкретный подкласс, реализующий абстрактный класс, определяет поведение только абстрактных операций через реализацию методов, а поведение шаблонного метода наследуется. Если шаблонный метод определен как final, то возможности подкласса ограничены описанием работы отдельных частей.

Примечание: не следует в шаблонном методе вызывать слишком много абстрактных методов, в этом случае суперкласс становится неудобно использовать. Шаблонный метод должен вызывать лишь несколько абстрактных.

AbstractTemplate
InputStream
Абстрактный класс (или конкретный, см. варианты), содержащий шаблонный метод.
templateMethod()
public int read(byte b[], int off, int len)
// Reads up to len bytes of data from input stream into an array of bytes
Конкретный шаблонный метод (часто final), в своем теле вызывающий абстрактные методы.
operation1()
operation2()
public abstract int read()
// Reads the next byte of data from the input stream
Методы (как правило, абстрактные, но не обязательно), вызываемые шаблонным и описывающие специфическую для подкласса часть логики.
ConcreteTemplate
FileInputStream
Класс, унаследованный от шаблонного класса и реализующий необходимые его части.
operation1()
operation2()
public native int read()
Конкретные методы, описывающие специфическую для подкласса часть логики.

Примеры

  • Абстрактный класс java.io.InputStream имеет шаблонный абстрактный метод public int read(byte b[], int off, int len). Абстрактный метод реализован в FileInputStream.

Чем отличается

Factory Method (GoF) является частным случаем Template Method, по сути Factory Method это Template Method, который возвращает объект, реализующий интерфейс и он применяется с целью создания этого объекта И Factory Method и Template Method оба имеют очень похожую структуру, но главное отличие в разной цели. Цель Factory Method - порождающая, а цель Template Method - поведенческая.

Decorator Decorator, подобно Template Method, позволяет менять реализацию, но не внутри вызова метода, а перед/после вызова. Использует композицию, а не наследование.

Strategy также позволяет менять внутренности метода, но не через наследование, а через композицию.

Варианты

  1. В суперклассе можно использовать не абстрактные, а конкретные методы с поведением по-умолчанию. Такие конкретные методы называются hook-методами. Действует соглашение об именах: их называют ли do-something или something-Hook. По умолчанию используется определение этих методов из суперкласса, но при необходимости его можно заменить в подклассах. В этом случае суперкласс не обязан быть abstract. В документации обязательно (!) прописывать такие методы, так как иначе их невозможно отделить от обычных.

Ссылки

https://java-design-patterns.com/patterns/template-method/

https://github.com/iluwatar/java-design-patterns/tree/master/template-method

StackOverflow: Template design pattern in JDK, could not find a method defining set of methods to be executed in order

StackOverflow: Is Factory method pattern a specialized case of Template method pattern

https://refactoring.guru/design-patterns/template-method

Baeldung - Implementing the Template Method Pattern in Java