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.
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.
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");
}
Pobieranie Raport tekstowy
- 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.
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
}
}
- 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 gdyZapisz()jest wspólny dla wszystkich. W fasadzie klasaFasadaLogowania"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().
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ę →