Zastosowanie
Metoda szablonowa
(ang. Template method
) (wzorzec behawioralny) ma za zadanie zdefiniować szkielet algorytmu, który jest otwarty na wprowadzanie zmian do wybranych jego części. Szablon ten składa się z operacji niezmiennych zdefiniowanych w klasie bazowej oraz z metod zmiennych tzw. haczyków
, które przyjmują implementacje zależną od klas pochodnych. Dzięki temu zmniejsza się nadmiarowość kodu, a dokonanie w nim zmian staje się mniej kosztowne. Można powiedzieć, że metoda szablonowa dostarcza pewien standard realizacji tego samego zadania na różne sposoby.
Ograniczenia
Wykorzystując wzorzec Metoda szablonowa
w celu uniknięcia łamania zasady podstawienia Liskov
należy zapewnić odpowiednią kontrolę dostępu do metod haczyków
poprzez wymuszenie nadpisania (metoda abstrakcyjna
) lub użycie chronionego modyfikatora dostępu. Metody niezmienne należy ukryć. Ze względu na konieczność przesłonięcia abstrakcyjnych metod haczyków w klasach pochodnych, warto dążyć do ich minimalizacji. Pozostałe haczyki mogą, ale nie muszą posiadać domyślnej implementacji. Decydując się na opcjonalne nadpisanie metod należy mieć pewność, że nie zaburzy to działania metody szablonowej. Im większa ilość kroków w metodzie szkieletu tym trudniejsze może być jej utrzymanie.
Użycie
Metoda szablonowa
wykorzystywana jest w celu eliminacji powtórzeń kodu w metodach o tym samym przeznaczeniu, ale o różnej implementacji (w pewnych częściach) zależnej od podklas. Ponadto używa się jej tam, gdzie od metod o różnej implementacji oczekuje się podobnego sposobu działania.
Implementacja
Klasa abstrakcyjna AbstractClass
definiuje szkielet metody szablonowej templateMethod
, dostarcza implementacje dla metod niezmiennych o prywatnym modyfikatorze dostępu oraz wymusza nadpisanie abstrakcyjnej metody zmiennej. Klasy rozszerzające dostarczają implementacji dla wszystkich metod zmiennych.
Poniższy listing przedstawia implementację metody szablonowej w klasie AbstractClass
oraz rozszerzenie implementacji w klasach pochodnych.
Klient tworzy obiekt żądanego typu i wywołuje na nim metodę szablonową, która wykonuje operacje w sposób dedykowany dla implementacji swojej klasy.
Przykład
Aplikacja Navigation
poza swoją podstawową funkcjonalnością nawigowania oraz wyszukiwania trasy, umożliwia personalizowanie zapytania dla wybranych środków transportu RouteFinder
(samochód CarRoute
, ciężarówka, pieszo, transport publiczny PublicTransportRoute
itp). Pomimo zachodzących różnic w sposobie znajdywania trasy, każdy proces wyszukiwania powinien przebiegać zgodnie ze stałym schematem (przetwarzanie zapytania, logowanie, zapis do historii, wyszukiwanie). Ponadto niektóre metody (np.: logowanie czy zapis) posiadają domyślną implementacje, jednakże ich zachowania mogą zostać nadpisane lub całkowicie pominięte. Dostawca rozkładów jazdy dla publicznych środków transportu wymaga przesłania informacji o pełnym zapytaniu użytkownika. Ze względu na powtarzalność kodu procesu wyszukiwania trasy, spełnienia wymogu spójnego zachowania tych procesów oraz możliwości edycji niektórych zachowań, problem ten może zostać zrealizowany przy użyciu wzorca Metoda szablonowa
co przedstawia poniższy listing.
W oknie mapy użytkownik personalizuje zapytanie wyszukania trasy. Wybiera środek transportu oraz definiuje miejsce początkowe i docelowe.
Biblioteki
Wzorzec Metody szablonowej
wykorzystywany jest m.in. w bibliotekach wspomagających automatyzację testów jednostkowych np.: jUnit
. Ponadto idea wzorca znajduje zastosowanie tam, gdzie zachodzi pewien stały cykl życia obiektu. Cykl życia Aktywności
w Androidzie
może być rozpatrywany w kontekście idei Metody szablonowej
. W standardowym pakiecie Java wszystkie nieabstrakcyjne metody klas strumieniowych InputStream, OutputStream, Reader, Writer oraz kolekcji AbstractList, AbstractSet i AbstractMap są przykładem Metody szablonowej
.