
Wzorce projektowe - Template method
Do takiej grupy z pewnością należy zaklasyfikować template method, który po polsku nazywamy metodą szablonową. Template method zaliczamy do zespołu tzw. wzorców zachowań.
Idea wzorca
Template method jest w moim odczuciu jednym z najprostszych wzorców projektowych — bardzo łatwo jest go zastosować, nawet nie zdając sobie z tego sprawy. Podczas tworzenia różnorakich fragmentów kodu często zdarza nam się dojść do sytuacji, w której uzyskujemy zbliżone do siebie klasy, różniące się pewnymi detalami implementacyjnymi. W takiej sytuacji przed oczami staje nam całe spektrum wzorców oraz rozwiązań. Bardzo łatwo można poczuć się przytłoczonym.
Przedstawiona powyżej sytuacja to duże pole do popisu dla template method. Wzorzec metody szablonowej wykorzystuje klasę abstrakcyjną do zaimplementowania lub utworzenia deklaracji wspólnych metod oraz swoistą metodę run, która w odpowiedniej kolejności wywołuje wszystkie metody pośrednie.
W ten sposób tworzymy łańcuch wywołań, w którym w poszczególnych implementacjach możemy wymieniać składniki. Przykład zaprezentowano na diagramie.
W klasie bazowej znajdują się metoda szablonowa oraz trzy metody cząstkowe. Klasy konkretne dziedziczą z klasy bazowej i jednocześnie implementują metodę nazwaną methodTwo, która różni się pomiędzy poszczególnymi implementacjami.
Przykład praktyczny
Wyobraźmy sobie, że tworzymy aplikację mobilną, która do generowania layoutu wykorzystuje klasy. Przy dostępnych obecnie kontrolkach oraz wykorzystaniu szeroko rozumianego layoutu adaptacyjnego istnieje spora szansa na podzielenie kodu layoutu w taki sposób, by częściowo reużyć tych samych jego fragmentów w wersji potrait oraz landscape. Jednocześnie oba widoki będą się składały z takich samych elementów.
Poniżej kod klasy abstrakcyjnej — bazy dla obu layotuów:
[sourcecode language="csharp"]
public abstract class LayoutBase
{
protected virtual void RenderHeader()
{
Console.WriteLine("LayoutBase:RenderHeader()");
}
protected abstract void RenderBody();
protected virtual void RenderFooter()
{
Console.WriteLine("LayoutBase:RenderFooter()");
}
public void BuildLayout()
{
RenderHeader();
RenderBody();
RenderFooter();
}
}
[/sourcecode]
Jak nietrudno zauważyć, metoda BuildLayout pełni funkcję metody szablonowej i wykorzystuje trzy metody podrzędne, z których dwie zostały już zdefiniowane, a trzecia powinna być zaimplementowana przez klasy konkretne. Warto również zwrócić uwagę na słowo kluczowe virtual. Zakładamy potencjalną zmienność dowolnego ze składników oraz stałość samej metody szablonowej.
Poniżej implementacja dwóch klas konkretnych — po jednej dla każdego z layoutów:
[sourcecode language="csharp"]
public class LayoutPortrait : LayoutBase
{
protected override void RenderBody()
{
Console.WriteLine("LayoutPortrait:RenderBody()");
}
}
public class LayoutLandscape : LayoutBase
{
protected override void RenderBody()
{
Console.WriteLine("LayoutLandscape:RenderBody()");
}
}
[/sourcecode]
W obu przypadkach zaimplementowaliśmy abstrakcyjną metodę RenderBody, ale nic nie stało na przeszkodzie, by np. nadpisać również jeden ze składników. Wzorzec template method daje na tym polu sporą elastyczność.
Zwieńczeniem przykładu jest testowa klasa Program:
[sourcecode language="csharp"]
public class Program
{
public static void Main(string[] args)
{
LayoutPortrait portrait = new LayoutPortrait();
portrait.BuildLayout();
LayoutLandscape landscape = new LayoutLandscape();
landscape.BuildLayout();
Console.Read();
}
}
[/sourcecode]
Wynik jej działania w konsoli powinien być zgodny z oczekiwanym:
LayoutBase:RenderHeader()
LayoutPortrait:RenderBody()
LayoutBase:RenderFooter()
LayoutBase:RenderHeader()
LayoutLandscape:RenderBody()
LayoutBase:RenderFooter()
Podsumowanie
Wzorca template method — jak wszystkiego w życiu — warto używać z rozwagą. Zasadniczo jest on prostą receptą na rozwiązanie wielu problemów powtarzającego się kodu. Oczywiście należy znaleźć rozsądną granicę. Jeśli kod osiągnie kilkaset linii, a metoda szablonowa będzie się składać z 10 metod cząstkowych, to powinien być dla nas sygnał, że jednak coś tu nie do końca zagrało.
Zobacz nasze propozycje
-
(druk)
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
Rozmowa kwalifikacyjna. O czym nie wiedzą kandydaci do pracy, czyli sekrety rekrutujących. Wydanie 5(druk)
(28.20 zł najniższa cena z 30 dni)
28,20 zł47,00 zł -
(47.40 zł najniższa cena z 30 dni)
47,40 zł79,00 zł -
(53.40 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(65.40 zł najniższa cena z 30 dni)
65,40 zł109,00 zł -
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(22.20 zł najniższa cena z 30 dni)
22,20 zł37,00 zł -
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(druk)
(77.35 zł najniższa cena z 30 dni)
71,40 zł119,00 zł -
(59.40 zł najniższa cena z 30 dni)
59,40 zł99,00 zł -
(47.40 zł najniższa cena z 30 dni)
47,40 zł79,00 zł -
(druk)
(57.85 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(druk)
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(40.20 zł najniższa cena z 30 dni)
40,20 zł67,00 zł -
(46.20 zł najniższa cena z 30 dni)
46,20 zł77,00 zł -
(59.40 zł najniższa cena z 30 dni)
59,40 zł99,00 zł -
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(druk)
(47.40 zł najniższa cena z 30 dni)
47,40 zł79,00 zł -
(53.40 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(24.95 zł najniższa cena z 30 dni)
29,94 zł49,90 zł