воскресенье, 23 августа 2026 г.


Паттерн «Шаблонный метод» (Template Method) — это поведенческий ООП-паттерн, в котором базовый класс определяет «скелет» алгоритма, а подклассы переопределяют отдельные его шаги, не меняя общей структуры. В C# это обычно реализуется как абстрактный (или частично абстрактный) класс с финальным публичным методом, внутри которого вызываются виртуальные/абстрактные методы-шаги.bool+1

Что такое «Шаблонный метод»

Назначение:

  • Определить шаблон (каркас) алгоритма в базовом классе.

  • Выделить шаги, которые могут различаться в подклассах.

  • Сделать эти шаги виртуальными или абстрактными, чтобы наследники могли их переопределять.radioprog+1

Классическая структура:

text
public 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

Плюсы паттерна

  1. Устранение дублирования кода
    Общий алгоритм вынесен в базовый класс, подклассы содержат только отличия.bool

  2. Единая точка контроля порядка шагов
    Порядок выполнения шагов фиксируется в шаблонном методе, его нельзя случайно «перепутать» в подклассах.radioprog

  3. Простое расширение
    Чтобы добавить новую вариацию алгоритма, нужно просто создать новый подкласс и переопределить нужные шаги.bool

  4. Инкапсуляция алгоритма
    Клиенты не знают деталей реализации шагов, взаимодействуют только с шаблонным методом.radioprog

Минусы паттерна

  1. Нарушение принципа инверсии зависимостей (в классическом виде)
    Подклассы зависят от базового класса, а не наоборот; изменение базового класса может ломать много наследников.radioprog

  2. Сложность при большом числе шагов
    Если алгоритм многошаговый и с множеством вариантов, абстрактный класс может стать громоздким и трудным для понимания.radioprog

  3. Ограниченная гибкость по сравнению с «Стратегией»
    Шаблонный метод работает через наследование, а не через передачу объектов-стратегий; изменить поведение в runtime сложнее.bool

  4. Риск «тяжелых» базовых классов
    При частом дроблении шагов и их вариаций базовый класс может превращаться в «монолит» с множеством виртуальных методов.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

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

Примеры кода в контексте .NET

1. Обработка данных (файл, блог, API)

text
public abstract class DataPipeline<T> { public void Run() { var source = LoadSource(); var items = Parse(source); items = Transform(items); Save(items); } protected abstract T LoadSource(); protected abstract IEnumerable<string> Parse(T source); protected virtual IEnumerable<string> Transform(IEnumerable<string> items) => items; protected abstract void Save(IEnumerable<string> items); } public class FilePipeline : DataPipeline<string> { protected override string LoadSource() { // чтение файла return System.IO.File.ReadAllText("input.txt"); } protected override IEnumerable<string> Parse(string source) { return source.Split('\n'); } protected override void Save(IEnumerable<string> items) { System.IO.File.WriteAllLines("output.txt", items); } }

2.wurf-сервис (веб, консоль, тест)

text
public 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-приложениях он всё ещё актуален, особенно в фреймворках и библиотеках, но в простых сценариях часто заменяется композицией и делегированием.

Комментариев нет:

Отправить комментарий