Menu
Coddy logo textTech

Wzorzec metody szablonowej

Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 59 z 70.

Wzorzec Template Method to wzorzec behawioralny, który definiuje szkielet algorytmu w klasie bazowej, umożliwiając podklasom nadpisywanie określonych kroków bez zmieniania ogólnej struktury. Klasa bazowa kontroluje przepływ pracy, a klasy pochodne dostosowują poszczególne elementy.

Ten wzorzec wykorzystuje dziedziczenie i metody abstrakcyjne. Klasa bazowa zawiera „metodę szablonową”, która wywołuje sekwencję kroków, z których niektóre są abstrakcyjne i muszą zostać zaimplementowane przez podklasy:

public abstract class DataProcessor
{
    // Metoda szablonowa - określa strukturę algorytmu
    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");
}

Każda podklasa zapewnia własną implementację, a klasa bazowa wymusza kolejność operacji:

DataProcessor csv = new CsvProcessor();
csv.Process();
// Odczytywanie pliku CSV
// Parsowanie danych CSV
// Zapisywanie w domyślnej lokalizacji

DataProcessor json = new JsonProcessor();
json.Process();
// Odczytywanie pliku JSON
// Parsowanie danych JSON
// Zapisywanie w chmurze

Wzorzec Template Method sprawdza się idealnie, gdy wiele klas ma tę samą strukturę algorytmu, ale różni się poszczególnymi krokami. Ułatwia ponowne wykorzystanie kodu, umieszczając wspólną logikę w klasie bazowej, a jednocześnie zapewnia elastyczność dzięki metodom, które można przesłaniać.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system generowania raportów z użyciem wzorca Metody Szablonowej. Różne typy raportów (takie jak raporty sprzedaży i raporty magazynowe) mają tę samą ogólną strukturę — wszystkie muszą zebrać dane, sformatować je i wyświetlić wynik — ale każdy typ raportu obsługuje te kroki inaczej.

Rozmieścisz swój kod w trzech plikach:

  • ReportGenerator.cs: Utwórz abstrakcyjną klasę ReportGenerator w przestrzeni nazw Reporting. Ta klasa bazowa definiuje szkielet algorytmu generowania raportów za pomocą metody szablonowej o nazwie Generate(). Metoda powinna wywołać trzy kroki w podanej kolejności: GatherData(), FormatReport() i OutputReport(). Oznacz GatherData() i FormatReport() jako abstrakcyjne (każdy typ raportu zaimplementuje je inaczej), natomiast OutputReport() powinna być metodą wirtualną z domyślną implementacją, która wyświetla Sending to default printer.
  • ConcreteReports.cs: Utwórz w tej samej przestrzeni nazw dwie konkretne klasy raportów dziedziczące po ReportGenerator:
    • SalesReport — implementuje GatherData(), aby wyświetlać Collecting sales data from database, oraz FormatReport(), aby wyświetlać Formatting as sales summary
    • InventoryReport — implementuje GatherData(), aby wyświetlać Scanning warehouse inventory, FormatReport(), aby wyświetlać Formatting as inventory list, oraz nadpisuje OutputReport(), aby wyświetlać Sending to warehouse manager
  • Program.cs: Połącz wszystkie elementy, tworząc instancje raportów i generując je. Metoda szablonowa sprawia, że każdy raport przechodzi ten sam trzyetapowy proces, ale konkretne zachowanie każdego kroku zależy od typu raportu.

Otrzymasz jedno wejście:

  • Typ raportu: sales lub inventory

Utwórz odpowiedni generator raportów na podstawie wejścia i wywołaj jego metodę Generate().

Na przykład, jeśli wejściem jest sales, wyjście powinno wyglądać następująco:

Collecting sales data from database
Formatting as sales summary
Sending to default printer

Jeśli wejściem jest inventory, wyjście powinno wyglądać następująco:

Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse manager

Zwróć uwagę, że oba raporty korzystają z dokładnie tej samej struktury algorytmu (zbieranie, formatowanie, wyświetlanie), ale implementacja każdego kroku jest dostosowana do potrzeb. SalesReport korzysta z domyślnego zachowania wyświetlania, natomiast InventoryReport je nadpisuje — pokazuje to, jak wzorzec Metody Szablonowej pozwala określić, które kroki trzeba nadpisać, a które można dostosować opcjonalnie!

Spróbuj swoich sił

using System;
using Reporting;

class Program
{
    public static void Main(string[] args)
    {
        string reportType = Console.ReadLine();
        
        // TODO: Utwórz odpowiedni generator raportu na podstawie reportType
        // Jeśli reportType ma wartość "sales", utwórz SalesReport
        // Jeśli reportType ma wartość "inventory", utwórz InventoryReport
        // Następnie wywołaj metodę Generate() dla raportu
        
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C# online