Паттерн «Шаблонный метод» (Template Method) — это поведенческий ООП-паттерн, в котором базовый класс определяет «скелет» алгоритма, а подклассы переопределяют отдельные его шаги, не меняя общей структуры. В C# это обычно реализуется как абстрактный (или частично абстрактный) класс с финальным публичным методом, внутри которого вызываются виртуальные/абстрактные методы-шаги.bool+1
Что такое «Шаблонный метод»
Назначение:
Определить шаблон (каркас) алгоритма в базовом классе.
Выделить шаги, которые могут различаться в подклассах.
Сделать эти шаги виртуальными или абстрактными, чтобы наследники могли их переопределять.radioprog+1
Классическая структура:
textpublic abstract class Processor
{
// Шаблонный метод — финальный, клиенты работают только с ним
public void Process()
{
Prepare();
var data = LoadData();
Transform(data);
SaveData(data);
Cleanup();
}
// Стандартный шаг — можно переопределять, но не обязательно
protected virtual void Prepare()
{
// базовая логика
}
// Обязательный шаг — переопределяется в подклассах
protected abstract long LoadData();
// optional шаг
protected virtual void Transform(long data)
{
// базовая трансформация
}
// another обязательный шаг
protected abstract void SaveData(long data);
// cleanup
protected virtual void Cleanup()
{
// базовая очистка
}
}
public class FileProcessor : Processor
{
protected override long LoadData()
{
// читаем из файла
return 123;
}
protected override void SaveData(long data)
{
// записываем в файл
}
protected override void Transform(long data)
{
// специфичная трансформация для файлов
}
}
Клиент работает только с Process(), а детали реализации шагов скрыты в подклассах.bool+1
Плюсы паттерна
Устранение дублирования кода Общий алгоритм вынесен в базовый класс, подклассы содержат только отличия.bool
Единая точка контроля порядка шагов Порядок выполнения шагов фиксируется в шаблонном методе, его нельзя случайно «перепутать» в подклассах.radioprog
Простое расширение Чтобы добавить новую вариацию алгоритма, нужно просто создать новый подкласс и переопределить нужные шаги.bool
Инкапсуляция алгоритма Клиенты не знают деталей реализации шагов, взаимодействуют только с шаблонным методом.radioprog
Минусы паттерна
Нарушение принципа инверсии зависимостей (в классическом виде) Подклассы зависят от базового класса, а не наоборот; изменение базового класса может ломать много наследников.radioprog
Сложность при большом числе шагов Если алгоритм многошаговый и с множеством вариантов, абстрактный класс может стать громоздким и трудным для понимания.radioprog
Ограниченная гибкость по сравнению с «Стратегией» Шаблонный метод работает через наследование, а не через передачу объектов-стратегий; изменить поведение в runtime сложнее.bool
Риск «тяжелых» базовых классов При частом дроблении шагов и их вариаций базовый класс может превращаться в «монолит» с множеством виртуальных методов.radioprog
Когда и где применяется
Паттерн удобен, когда:
Есть схожие алгоритмы с одинаковой общей структурой, но разными деталями отдельных шагов.bool
Нужно фиксировать порядок шагов и гарантировать, что подклассы не будут его нарушать.radioprog
В будущем планируется создавать много подклассов, каждый со своей вариацией алгоритма.bool
В коде есть дублирование похожих алгоритмов в разных классах — их можно объединить в шаблонный метод.bool
Примеры использования в .NET:
WCF: классы вроде CommunicationObject, ChannelBase, ServiceHostBase используют шаблонный метод: публичные методы Open, Close и т.п. sealed, но внутри вызывают виртуальные/абстрактные OnOpen, OnClose.bool
Любой абстрактный класс с защищёнными абстрактными/виртуальными методами, которые вызываются из общего публичного метода, фактически является примером Template Method.bool
Утратил ли паттерн актуальность в C#
Нет, паттерн не утратил актуальность, но его применение стало более осознанным:
В современных подходах (чистая архитектура, композиция вместо наследования) часто предпочитают стратегию + делегирование вместо глубоких базовых классов с множеством виртуальных шагов.jasulib
Однако для фреймворков и базовых классов (например, сервисы обработки, workflow-механизмы) Template Method остаётся удобным способом предоставить «скелет» алгоритма иAllowing пользователям переопределять детали.jasulib+1
В .NET Aspire, Dapr-подобных архитектурах и библиотечных абстракциях этот паттерн всё ещё активно используется для построения гибких, но контролируемых алгоритмов.jasulib
Таким образом, паттерн остался важным инструментом, особенно в библиотека и фреймворках, но в простых приложениях его часто заменяют более композиционными решениями.
textpublic abstract class ReportService
{
public void GenerateReport()
{
var data = CollectData();
Format(data);
Export(data);
}
protected abstract IEnumerable<DataItem> CollectData();
protected virtual void Format(IEnumerable<DataItem> data) { }
protected abstract void Export(IEnumerable<DataItem> data);
}
public class WebReportService : ReportService
{
protected override IEnumerable<DataItem> CollectData()
{
// сбор данных из API / БД
return new List<DataItem>();
}
protected override void Export(IEnumerable<DataItem> data)
{
// возврат HTML / JSON клиенту
}
}
Эти примеры показывают типичное применение: один публичный метод, набор шагов, часть обязательных, часть переопределяемых по желанию.radioprog+1
Если кратко:
Шаблонный метод — это «каркас алгоритма + переопределяемые шаги».
Плюсы: устранение дублирования, контроль порядка, простое расширение.
Минусы: сильная связь через наследование, риск громоздких базовых классов, меньше гибкости чем у Стратегии.
В современных .NET-приложениях он всё ещё актуален, особенно в фреймворках и библиотеках, но в простых сценариях часто заменяется композицией и делегированием.
Комментариев нет:
Отправить комментарий