Dlaczego Template Method Pattern jest ważny?
W programowaniu często spotykamy sytuacje gdzie różne klasy wykonują podobne operacje, ale z drobnymi różnicami. Template Method pattern rozwiązuje ten problem eliminując duplikację kodu i zapewniając spójną strukturę procesów biznesowych. To fundamentalny wzorzec używany w Spring Framework, Apache Commons i wielu innych bibliotekach Java.
Co się nauczysz:
- Czym jest Template Method pattern i kiedy go używać
- Jak implementować wzorzec w Javie 8 krok po kroku
- Praktyczne przykłady z życia wzięte
- Najczęstsze błędy początkujących i jak ich unikać
- Różnice między Template Method a Strategy pattern
Wymagania wstępne:
- Podstawowa znajomość Javy (klasy, dziedziczenie, metody abstrakcyjne)
- Rozumienie pojęć: polimorfizm, hermetyzacja
- 6-12 miesięcy doświadczenia z programowaniem obiektowym
Czym jest Template Method Pattern?
Template Method to behawioralny wzorzec projektowy który definiuje szkielet algorytmu w metodzie klasy bazowej, delegując niektóre kroki do klas pochodnych. Klasy pochodne mogą przedefiniować poszczególne kroki algorytmu bez zmiany jego ogólnej struktury.
Praktyczny przykład – System raportowania
Wyobraź sobie że musisz stworzyć system generujący różne typy raportów: PDF i Excel. Oba mają podobną strukturę, ale różnią się formatowaniem.
// Klasa abstrakcyjna definiująca template method public abstract class ReportGenerator { // Template method - szkielet algorytmu public final void generateReport() { collectData(); formatHeader(); formatData(); formatFooter(); saveReport(); } // Metody wspólne dla wszystkich raportów protected void collectData() { System.out.println("Zbieranie danych z bazy....."); } protected void saveReport() { System.out.println("Zapisywanie raportu na dysk..."); } // Metody abstrakcyjne - do implementacji w klasach pochodnych protected abstract void formatHeader(); protected abstract void formatData(); protected abstract void formatFooter(); }
// Konkretna implementacja dla PDF public class PDFReportGenerator extends ReportGenerator { @Override protected void formatHeader() { System.out.println("Formatowanie nagłówka PDF z logo..."); } @Override protected void formatData() { System.out.println("Formatowanie danych do tabeli PDF..."); } @Override protected void formatFooter() { System.out.println("Dodawanie stopki z numeracją stron PDF..."); } } // Konkretna implementacja dla Excel public class ExcelReportGenerator extends ReportGenerator { @Override protected void formatHeader() { System.out.println("Tworzenie nagłówka w pierwszym wierszu Excel..."); } @Override protected void formatData() { System.out.println("Wypełnianie komórek danymi Excel..."); } @Override protected void formatFooter() { System.out.println("Dodawanie formuł sumujących Excel..."); } }
Użycie wzorca w praktyce
public class ReportingService { public static void main(String[] args) { // Generowanie raportu PDF ReportGenerator pdfReport = new PDFReportGenerator(); pdfReport.generateReport(); System.out.println("---"); // Generowanie raportu Excel ReportGenerator excelReport = new ExcelReportGenerator(); excelReport.generateReport(); } }
Kluczowe cechy wzorca
public abstract class DataProcessor { public final void processData() { loadData(); if (shouldValidate()) { // Hook method validateData(); } transformData(); saveData(); } // Hook method z domyślną implementacją protected boolean shouldValidate() { return true; // Domyślnie zawsze waliduj } protected abstract void loadData(); protected abstract void transformData(); protected abstract void saveData(); private void validateData() { System.out.println("Walidacja danych..."); } }
Template Method vs Strategy Pattern
Template Method | Strategy Pattern |
---|---|
Używa dziedziczenia | Używa kompozycji |
Definiuje szkielet algorytmu | Enkapsuluje całe algorytmy |
Klasy pochodne nadpisują części | Obiekty strategy są wymienne |
Struktura algorytmu stała | Cały algorytm może się zmienić |
Wzorzec w praktyce – Spring Framework
Spring Framework intensywnie używa Template Method pattern. Przykład to JdbcTemplate który definiuje szablon dla operacji bazodanowych:
// Uproszczony przykład inspirowany Spring JDBC public abstract class JdbcOperations { public final ListexecuteQuery(String sql) { Connection conn = getConnection(); PreparedStatement stmt = prepareStatement(conn, sql); ResultSet rs = stmt.executeQuery(); List results = mapResults(rs); // Abstract method cleanup(conn, stmt, rs); return results; } protected abstract List mapResults(ResultSet rs); }
Używaj gdy masz kilka klas wykonujących podobne operacje z drobnymi różnicami. Wzorzec eliminuje duplikację kodu i zapewnia spójną strukturę procesów.
Tak, powinien być final żeby klasy pochodne nie mogły zmienić struktury algorytmu. Mogą tylko nadpisywać konkretne kroki.
To opcjonalne metody które klasy pochodne mogą nadpisać ale nie muszą. Mają domyślną implementację (często pustą) w klasie bazowej.
Template Method używa dziedziczenia i definiuje szkielet algorytmu. Strategy używa kompozycji i enkapsuluje całe algorytmy które są wymienne.
Tak, klasa może mieć kilka template methods dla różnych procesów. Każdy definiuje swój własny szkielet algorytmu.
Przydatne zasoby:
🚀 Zadanie dla Ciebie
Stwórz system przetwarzania plików używając Template Method pattern. Klasa bazowa powinna definiować kroki: otwórz plik, przetwórz zawartość, zapisz wynik, zamknij plik. Stwórz dwie implementacje: jedną dla plików tekstowych (zmiana na wielkie litery) i drugą dla plików CSV (dodanie numeru linii). Przetestuj oba warianty.