Что это такое
Паттерн Template Method фиксирует скелет алгоритма — шаги и их порядок, — позволяя при этом отдельным шагам различаться. Рецепт пишется один раз; каждый вариант заполняет свои шаги.
Классически скелет находится в базовом классе. В Go это делается функцией, которая принимает интерфейс: функция — это неизменный рецепт, а интерфейс хранит изменяемые шаги.
Пример: один рецепт, два напитка
MakeDrink владеет порядком: вскипятить, заварить, налить, добавки. Чай и кофе только отвечают, как заваривать и что добавить — они не могут переставить или пропустить шаги.
Скелет остаётся неизменным
Оба напитка проходят одни и те же четыре шага в одном и том же порядке, потому что порядок находится в одной функции. Новый напиток реализует два метода и наследует всю эту дисциплину.
Вывод: программа на Go и захваченный вывод
package main
import "fmt"
// Изменяемые шаги живут в интерфейсе...
type Steps interface {
Brew() string
Extras() string
}
// ...а неизменный скелет живёт в одной функции.
func MakeDrink(name string, s Steps) {
fmt.Println("--", name)
fmt.Println("вскипятить воду")
fmt.Println(s.Brew())
fmt.Println("налить в чашку")
fmt.Println(s.Extras())
}
type Tea struct{}
func (Tea) Brew() string { return "заварить чайные листья" }
func (Tea) Extras() string { return "добавить лимон" }
type Coffee struct{}
func (Coffee) Brew() string { return "пропустить воду через кофе" }
func (Coffee) Extras() string { return "добавить молоко" }
func main() {
MakeDrink("чай", Tea{})
MakeDrink("кофе", Coffee{})
}
Когда это использовать
Используйте, когда несколько процедур имеют одну и ту же фиксированную последовательность с разными деталями — формирование отчётов, конвейеры импорта, подготовка тестов.
Не используйте, когда вариантам нужен ещё и разный порядок — попытка втиснуть их в один скелет гнёт паттерн, пока он не сломается. А с одним-единственным вариантом скелет — это просто функция.
Плюсы и минусы
Плюсы: последовательность задаётся в одном месте; варианты не могут забыть шаг или переставить шаги; общие шаги написаны один раз.
Минусы: жёсткость по замыслу — вариант, которому нужно «почти то же самое, но...», борется со скелетом; слишком много методов-хуков делают рецепт трудным для понимания.