INF.04 · C# · lekcja 18

Wzorce projektowe — Metoda szablonowa, Fasada, Kompozyt

Dobierz wzorzec do problemu

  • Zrozum
  • Sprawdź
  • Napisz sam

Po tej lekcji: dobierz wzorzec do problemu

Dzisiaj zrobisz konkretną rzecz

Wzorce projektowe to sygnał dla oceniającego (nauczyciela, egzaminatora, przyszłego pracodawcy), że rozumiesz nie tylko SKŁADNIĘ C#, ale też jak dobrze ORGANIZOWAĆ kod w większych projektach — to wiedza, która odróżnia programistę piszącego działający kod od programisty piszącego kod, który da się później utrzymać i rozwijać.

Pilot samolotu naciska jeden przycisk "autopilot" (fasada), nie martwiąc się dziesiątkami systemów, które ten jeden przycisk uruchamia pod spodem. Struktura folderów na Twoim komputerze to z kolei klasyczny kompozyt — folder może zawierać pliki i inne foldery, a "rozmiar folderu" liczy się tak samo niezależnie od głębokości zagnieżdżenia.

Sprawdź w działaniu

Dobierz wzorzec do problemu

Najpierw przewidź wynik. Zmień dane w modelu i porównaj efekt. Spróbuj także przypadku granicznego, a nie tylko pierwszego poprawnego przykładu.

Ta interakcja wymaga włączonego JavaScriptu.

Model pokazuje wybraną zasadę. Nie uruchamia ani nie ocenia wklejonego kodu C#.

1. Przygotuj i uruchom własny projekt

2. Najpierw mały przykład

Wykonaj tę próbę przed dłuższym rozwiązaniem. Metoda szablonowa ustala kolejność etapów w Wykonaj, a klasa pochodna dostarcza brakujący krok. Fasada upraszcza dostęp do kilku podsystemów, Kompozyt łączy elementy i grupy w drzewo — poniżej zachowane są osobne przykłady.

Program.cscsharp
Raport raport = new RaportTekstowy();
raport.Wykonaj();

abstract class Raport
{
    public void Wykonaj() { Pobierz(); Pokaz(); }
    private void Pobierz() => Console.WriteLine("Pobieranie");
    protected abstract void Pokaz();
}
class RaportTekstowy : Raport
{
    protected override void Pokaz() => Console.WriteLine("Raport tekstowy");
}
Wynik
Pobieranie
Raport tekstowy
  1. Co sprawdzić? Zmień jedną wartość i przed uruchomieniem zapisz przewidywany rezultat. Porównaj go z opisem wyniku; przy błędzie wróć do konkretnej instrukcji.

Jak to działa — 1

Wzorzec projektowy to SPRAWDZONE, nazwane rozwiązanie często powtarzającego się problemu projektowego — zamiast wymyślać rozwiązanie od zera, korzystasz z gotowego "przepisu", który wielu programistów przed Tobą uznało za dobry. Podstawa programowa wymienia wprost trzy wzorce, którymi zajmiemy się w tej lekcji.

Metoda szablonowa (Template Method) — klasa bazowa definiuje SZKIELET algorytmu (kolejność kroków), ale pozwala klasom pochodnym nadpisać POJEDYNCZE kroki, nie cały proces. To rozszerzenie tego, co już znasz z Lekcji 14-14 (metody wirtualne + klasy abstrakcyjne) — tutaj metoda "organizująca" jest zwykła (niewirtualna), a tylko poszczególne kroki wewnątrz są wirtualne/abstrakcyjne.

Fasada (Facade) — jedna, PROSTA klasa "ukrywająca" skomplikowaną współpracę wielu innych klas za wygodnym, czytelnym interfejsem. Użytkownik fasady nie musi wiedzieć, ile klas i jak dokładnie współpracuje pod spodem — woła jedną prostą metodę, a cała złożoność jest ukryta w środku.

Jak to działa — 2

Kompozyt (Composite) — pozwala traktować POJEDYNCZY obiekt i GRUPĘ obiektów w JEDNAKOWY sposób, przez wspólny interfejs/klasę bazową. Klasyczny przykład: folder w systemie plików może zawierać zarówno pojedyncze pliki, jak i inne foldery (które z kolei zawierają kolejne pliki/foldery) — a obliczenie "całkowitego rozmiaru" działa identycznie, niezależnie od tego, ile poziomów zagnieżdżenia ma struktura.

Wszystkie trzy wzorce bazują na tym, czego nauczyłeś się we wcześniejszych lekcjach (dziedziczenie, polimorfizm, hermetyzacja) — nie są nową składnią C#, tylko sposobem UKŁADANIA już znanych narzędzi w sprawdzony, powtarzalny sposób.

3. Pełny przykład — czytaj od Main

Teraz zastąp Program.cs tym programem. Zanim uruchomisz, znajdź dane wejściowe, operację i miejsce prezentacji wyniku. W tym wariancie zachowujemy jawny Main. Nie wklejaj kilku pełnych programów do jednego pliku.

Program.cs — osobne uruchomieniecsharp
using System;

// --- METODA SZABLONOWA ---
abstract class PrzygotowanieRaportu
{
    // metoda szablonowa - definiuje STAŁĄ kolejność kroków
    public void Wykonaj()
    {
        PobierzDane();
        Przetworz();
        Zapisz();
    }

    protected abstract void PobierzDane();
    protected abstract void Przetworz();

    protected void Zapisz() // wspólny krok, ten sam dla wszystkich raportów
    {
        Console.WriteLine("Raport zapisany do pliku.");
    }
}

class RaportSprzedazy : PrzygotowanieRaportu
{
    protected override void PobierzDane() => Console.WriteLine("Pobieram dane sprzedaży...");
    protected override void Przetworz() => Console.WriteLine("Liczę sumy sprzedaży...");
}

// --- FASADA ---
class SilnikSerwisu
{
    public void SprawdzHaslo(string haslo) => Console.WriteLine("Sprawdzam hasło...");
    public void ZaladujProfil() => Console.WriteLine("Ładuję profil użytkownika...");
    public void ZapiszLogowanie() => Console.WriteLine("Zapisuję log logowania...");
}

class FasadaLogowania // ukrywa 3 osobne kroki za JEDNĄ prostą metodą
{
    private SilnikSerwisu silnik = new SilnikSerwisu();

    public void Zaloguj(string haslo)
    {
        silnik.SprawdzHaslo(haslo);
        silnik.ZaladujProfil();
        silnik.ZapiszLogowanie();
        Console.WriteLine("Zalogowano pomyślnie!");
    }
}

class Program
{
    static void Main()
    {
        PrzygotowanieRaportu raport = new RaportSprzedazy();
        raport.Wykonaj(); // ta sama kolejność kroków dla każdego raportu

        Console.WriteLine();

        FasadaLogowania logowanie = new FasadaLogowania();
        logowanie.Zaloguj("tajneHaslo123"); // jedno wywołanie zamiast trzech
    }
}
  1. Prześledź kod W metodzie szablonowej Wykonaj() NIE JEST wirtualna — jej kolejność kroków jest ZAWSZE taka sama dla każdego raportu. To poszczególne kroki (PobierzDane(), Przetworz()) są abstrakcyjne i różnią się w zależności od konkretnego typu raportu, podczas gdy Zapisz() jest wspólny dla wszystkich. W fasadzie klasa FasadaLogowania "chowa" przed użytkownikiem trzy osobne kroki logowania za jedną metodą Zaloguj() — użytkownik fasady nie musi wiedzieć, że w środku dzieje się aż tyle.

Sprawdź, zanim przepiszesz cały program

Częsty błąd to mylenie metody szablonowej ze zwykłym polimorfizmem (Lekcja 14) — kluczowa różnica to to, że metoda ORGANIZUJĄCA kolejność kroków (Wykonaj()) NIE jest nadpisywana, tylko POSZCZEGÓLNE kroki wewnątrz niej. Drugi błąd: fasada, która sama zawiera dużo logiki zamiast tylko DELEGOWAĆ pracę do innych klas — fasada ma być cienką, prostą warstwą "na wierzchu", nie kolejną skomplikowaną klasą. Trzeci: implementacja Kompozytu bez wspólnego interfejsu/klasy bazowej dla "pojedynczego elementu" i "grupy elementów" — bez tego nie da się traktować ich jednakowo, co jest całym sensem tego wzorca.

Ćwiczenie z pomocą · samodzielna praca

4. Teraz Twoja zmiana

Dodaj do przykładu z lekcji drugą klasę pochodną RaportMagazynu : PrzygotowanieRaportu z własną implementacją PobierzDane() i Przetworz().

Oczekiwany rezultat
Spełnij warunki polecenia. Zapisz wejście, otrzymany wynik i wyjaśnij, która część kodu za niego odpowiada.
Potrzebujesz pomocy? Rozwiązuj krok po kroku.
Krok 1 — pokaż podpowiedź

Wróć do podstawowej formy oraz objaśnienia: Metoda szablonowa ustala kolejność etapów w Wykonaj, a klasa pochodna dostarcza brakujący krok. Fasada upraszcza dostęp do kilku podsystemów, Kompozyt łączy elementy i grupy w drzewo — poniżej zachowane są osobne przykłady.

Krok 2 — pokaż podpowiedź

Zmień tylko część potrzebną do polecenia. Zachowaj działającą wersję przed zmianą i uruchamiaj po każdym małym etapie.

Krok 3 — pokaż podpowiedź

Sprawdź przypadek zwykły i graniczny; porównaj z regułą: Pobieranie Raport tekstowy

Otwórz tylko tyle podpowiedzi, ile potrzebujesz. Po każdym kroku wróć do zadania i sprawdź wynik.

5. Sprawdź rozumienie, nie tylko uruchomienie

Dalej na swoim koncie

Rozgrzewki, quiz i zadania są w biurku ucznia.

Teoria jest otwarta dla wszystkich. Żeby rozwiązywać zadania, zapisywać szkice i widzieć swój postęp, zaloguj się.

Zaloguj się →
Źródła i dalsza nauka