Lekcja 18. Wzorce projektowe — Metoda szablonowa, Fasada, Kompozyt
Trudny / egzaminacyjnyPo co się tego uczymy?
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ć.
Teoria
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.
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.
Przykład z życia
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.
Kod (C#)
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
}
}
Komentarz i wyjaśnienie kodu
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.
Ćwiczenie samodzielne
Dodaj do przykładu z lekcji drugą klasę pochodną RaportMagazynu : PrzygotowanieRaportu z własną implementacją PobierzDane() i Przetworz().
Plac zabaw — wypróbuj online
Poniższy kod wykonuje się od razu w Twojej przeglądarce — nic nie trzeba instalować. Zmień kod i kliknij „Uruchom”.
Zadania do pracy własnej
Zbuduj prostą fasadę
FasadaZamowieniaukrywającą trzy osobne kroki (sprawdzenie stanu magazynu, obciążenie karty, wysłanie potwierdzenia e-mail — wszystkie jako osobne metody wypisujące tekst) za jedną metodąZlozZamowienie().Zbuduj metodę szablonową dla procesu "przygotowania posiłku" (klasa abstrakcyjna
Przepisz metodąUgotuj()wywołującą po koleiPrzygotujSkladniki(),Gotuj()i wspólny krokPodaj()), i dwie klasy pochodne dla różnych potraw.Zbuduj uproszczony wzorzec Kompozyt dla struktury plików: wspólny interfejs
IElementPlikuz metodąint RozmiarKB(), klasaPlik(implementuje bezpośrednio, zwraca swój rozmiar) i klasaFolder(przechowujeList<IElementPliku>i zwraca SUMĘ rozmiarów wszystkich elementów — w tym zagnieżdżonych folderów). Zbuduj przykładową strukturę z folderami wewnątrz folderów i oblicz łączny rozmiar całości JEDNYM wywołaniem.
Typowe błędy
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.
Nawiązanie do egzaminu zawodowego
To bezpośrednia, dosłowna realizacja efektu INF.04.3.8 z podstawy programowej: "stosuje wzorce projektowe" — oficjalny tekst wymienia wprost jako przykłady "Metodę szablonową, Fasadę, Kompozyt", dokładnie te trzy wzorce omówione w tej lekcji.