Паттерн Шаблонный метод
Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy — урок 59 из 70.
Паттерн Шаблонный метод — это поведенческий паттерн, который определяет скелет алгоритма в базовом классе, позволяя подклассам переопределять конкретные шаги, не меняя общую структуру. Базовый класс управляет рабочим процессом, в то время как производные классы настраивают отдельные части.
Этот паттерн использует наследование и абстрактные методы. Базовый класс содержит «шаблонный метод», который вызывает последовательность шагов, некоторые из которых являются абстрактными и должны быть реализованы подклассами:
public abstract class DataProcessor
{
// Шаблонный метод — определяет структуру алгоритма
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected abstract void ProcessData();
protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}
public class CsvProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading CSV file");
protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}
public class JsonProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading JSON file");
protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
protected override void SaveData() => Console.WriteLine("Saving to cloud");
}Каждый подкласс предоставляет свою собственную реализацию, в то время как базовый класс определяет порядок выполнения операций:
DataProcessor csv = new CsvProcessor();
csv.Process();
// Чтение CSV файла
// Парсинг CSV данных
// Сохранение в расположение по умолчанию
DataProcessor json = new JsonProcessor();
json.Process();
// Чтение JSON файла
// Парсинг JSON данных
// Сохранение в облакоПаттерн Шаблонный метод (Template Method) идеально подходит в тех случаях, когда несколько классов имеют одинаковую структуру алгоритма, но различаются в конкретных шагах. Он способствует повторному использованию кода, размещая общую логику в базовом классе и обеспечивая гибкость за счет переопределяемых методов.
Задание
ЛегкоДавайте создадим систему генерации отчетов, используя паттерн Шаблонный метод (Template Method). Различные типы отчетов (например, отчеты по продажам и отчеты по инвентаризации) имеют общую структуру — всем им нужно собрать данные, отформатировать их и вывести результат — но каждый тип отчета обрабатывает эти шаги по-своему.
Вы организуете свой код в трех файлах:
ReportGenerator.cs: Создайте абстрактный классReportGeneratorв пространстве именReporting. Этот базовый класс определяет скелет алгоритма генерации отчета через шаблонный методGenerate(). Метод должен последовательно вызывать три шага:GatherData(),FormatReport()иOutputReport(). СделайтеGatherData()иFormatReport()абстрактными (каждый тип отчета будет реализовывать их по-разному), в то время какOutputReport()должен быть виртуальным методом с реализацией по умолчанию, которая выводитSending to default printer.ConcreteReports.cs: Создайте два конкретных класса отчетов в том же пространстве имен, которые наследуются отReportGenerator:SalesReport— реализуетGatherData()для выводаCollecting sales data from databaseиFormatReport()для выводаFormatting as sales summaryInventoryReport— реализуетGatherData()для выводаScanning warehouse inventory,FormatReport()для выводаFormatting as inventory listи переопределяетOutputReport()для выводаSending to warehouse manager
Program.cs: Объедините все вместе, создавая экземпляры отчетов и запуская их генерацию. Шаблонный метод гарантирует, что каждый отчет следует одному и тому же трехэтапному процессу, но конкретное поведение каждого шага варьируется в зависимости от типа отчета.
Вы получите один входной параметр:
- Тип отчета:
salesилиinventory
Создайте соответствующий генератор отчетов на основе входных данных и вызовите его метод Generate().
Например, если на входе sales, вывод должен быть следующим:
Collecting sales data from database
Formatting as sales summary
Sending to default printerЕсли на входе inventory, вывод должен быть следующим:
Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse managerОбратите внимание, как оба отчета следуют одной и той же структуре алгоритма (сбор, форматирование, вывод), но реализация каждого шага настроена индивидуально. SalesReport использует поведение вывода по умолчанию, в то время как InventoryReport переопределяет его — это демонстрирует, как паттерн Шаблонный метод позволяет вам контролировать, какие шаги обязательны для переопределения, а какие могут быть настроены по желанию!
Шпаргалка
Паттерн Шаблонный метод (Template Method) определяет основу алгоритма в базовом классе, позволяя подклассам переопределять определенные шаги, не изменяя общую структуру.
Базовый класс содержит «шаблонный метод», который вызывает последовательность шагов. Некоторые шаги являются абстрактными (должны быть реализованы подклассами), в то время как другие могут быть виртуальными (необязательными для переопределения):
public abstract class DataProcessor
{
// Шаблонный метод — определяет структуру алгоритма
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected abstract void ProcessData();
protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}Подклассы предоставляют свои собственные реализации, в то время как базовый класс обеспечивает соблюдение порядка операций:
public class CsvProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading CSV file");
protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}
public class JsonProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading JSON file");
protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
protected override void SaveData() => Console.WriteLine("Saving to cloud");
}Использование:
DataProcessor csv = new CsvProcessor();
csv.Process();
// Reading CSV file
// Parsing CSV data
// Saving to default location
DataProcessor json = new JsonProcessor();
json.Process();
// Reading JSON file
// Parsing JSON data
// Saving to cloudПаттерн «Шаблонный метод» идеален в тех случаях, когда несколько классов имеют одинаковую структуру алгоритма, но различаются в конкретных шагах. Он способствует повторному использованию кода, размещая общую логику в базовом классе и обеспечивая гибкость за счет переопределяемых методов.
Попробуйте сами
using System;
using Reporting;
class Program
{
public static void Main(string[] args)
{
string reportType = Console.ReadLine();
// TODO: Создать соответствующий генератор отчетов на основе reportType
// Если reportType равен "sales", создать SalesReport
// Если reportType равен "inventory", создать InventoryReport
// Затем вызвать метод Generate() у отчета
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыПространства имен и директивыВведение в классы и объектыКлючевое слово 'this'Методы и параметрыПоля и свойстваКонструкторыИнициализаторы объектовИтоги — Простой калькулятор4Наследование
Основы синтаксиса наследования (:)Ключевое слово 'base'Ключевые слова Virtual и OverrideЗапечатанные классыБазовый класс 'object'Итоги — Иерархия сотрудников7Продвинутые возможности
Перегрузка операторовИндексаторы (this[])Переопределение ToString()Методы расширенияПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПотокобезопасный SingletonПаттерн FactoryПаттерн Observer (События)Паттерн Strategy13Финальные испытания
Платформа для онлайн-обученияКомпонент игрового персонажаСервис аренды транспорта2Свойства и статические члены
Автоматически реализуемые свойстваСвойства только для чтения и записиСтатические поля и методыСтатические классыЧлены в виде выражений5Полиморфизм и интерфейсы
Полиморфизм: компиляция vs выполнениеИнтерфейс vs абстрактный классМножественные интерфейсыЯвные интерфейсыUpcasting и DowncastingИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция вместо наследованияGenerics (классы и методы)Делегаты и событияАтрибуты и рефлексияIDisposable и оператор usingОсновы Dependency Injection11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Архитектура классов
Экземплярные и статические данныеКлючевые слова 'readonly' и 'const'Опорные поляПовторение — Менеджер банковских счетов6Инкапсуляция
Модификаторы доступаСвойства для инкапсуляцииРеализация скрытия данныхПаттерны неизменяемостиИтоги — Записи студентов9Переменное количество аргументов
Ключевое слово 'params'Необязательные параметрыИменованные аргументыПерегрузка методов