Паттерн Шаблонный метод
Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy. Урок 59 из 70.
Паттерн Template Method — это поведенческий паттерн, который определяет скелет алгоритма в базовом классе, позволяя подклассам переопределять отдельные шаги, не изменяя общую структуру. Базовый класс управляет рабочим процессом, а производные классы настраивают отдельные части.
Этот паттерн использует наследование и abstract методы. base class содержит «шаблонный method», который calls последовательность шагов, некоторые из которых являются abstract и должны быть реализованы подклассами:
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");
}Каждый подкласс предоставляет собственную implementation, а базовый class обеспечивает порядок выполнения операций:
DataProcessor csv = new CsvProcessor();
csv.Process();
// Чтение CSV файла
// Парсинг CSV данных
// Saving to default location
DataProcessor json = new JsonProcessor();
json.Process();
// Чтение JSON файла
// Парсинг JSON данных
// Сохранение в облакоПаттерн Template Method идеально подходит, когда несколько классов имеют одинаковую структуру algorithm, но различаются на отдельных этапах. Он способствует повторному использованию кода, размещая общую логику в base class и обеспечивая гибкость с помощью методов, которые можно переопределить.
Задание
ЛегкоДавайте создадим систему генерации отчётов с использованием паттерна Template Method. Разные типы отчётов (например, отчёты о продажах и отчёты об инвентаре) имеют одинаковую общую структуру — всем им нужно собрать данные, отформатировать их и вывести результат, — но каждый тип отчёта обрабатывает эти шаги по-своему.
Вы организуете код в трёх файлах:
ReportGenerator.cs: создайте абстрактный классReportGeneratorв namespaceReporting. Этот базовый класс определяет каркас algorithm генерации отчёта с помощью template method под названиемGenerate(). method должен вызывать три шага по порядку:GatherData(),FormatReport()иOutputReport(). СделайтеGatherData()иFormatReport()абстрактными (каждый тип отчёта будет реализовывать их по-своему), аOutputReport()должен быть virtual method с реализацией по умолчанию, которая выполняет printSending to default printer.ConcreteReports.cs: создайте два конкретных класса отчётов в том же namespace, унаследованных отReportGenerator:SalesReport— реализуетGatherData(), чтобы выполнить printCollecting sales data from database, иFormatReport(), чтобы выполнить printFormatting as sales summaryInventoryReport— реализуетGatherData(), чтобы выполнить printScanning warehouse inventory,FormatReport(), чтобы выполнить printFormatting as inventory list, и переопределяетOutputReport(), чтобы выполнить printSending to warehouse manager
Program.cs: объедините всё вместе, создав экземпляры отчётов и сгенерировав их. template method гарантирует, что каждый отчёт выполняет один и тот же процесс из трёх шагов, но конкретное поведение каждого шага зависит от типа отчёта.
Вы получите один входной параметр:
- Тип отчёта:
salesилиinventory
Создайте подходящий генератор отчётов на основе входных данных и вызовите его method 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Обратите внимание, что оба отчёта следуют абсолютно одинаковой структуре algorithm (сбор, форматирование, вывод), но реализация каждого шага настраивается отдельно. SalesReport использует поведение вывода по умолчанию, а InventoryReport переопределяет его — это демонстрирует, как паттерн Template Method позволяет управлять тем, какие шаги обязательно переопределять, а какие можно при необходимости настраивать!
Попробуйте сами
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'Необязательные параметрыИменованные аргументыПерегрузка методовПотренируйтесь самостоятельно: Онлайн-компилятор C#