Press "Enter" to skip to content

Wzorce projektowe – Metoda szablonowa

Dzisiaj porozmawiamy sobie trochę na temat metody szablonowej. Wzorzec ten służy do określenia szkieletu algorytmu, aby w każdej klasie podrzędnej była zachowana kolejność wykonywanych czynności.

Wzorzec Metoda Szablonowa definiuje szkielet danego algorytmu w określonej metodzie, przekazując realizację niektórych jego kroków do klas podrzędnych. Wzorzec ten pozwala klasom podrzędnym na redefiniowanie pewnych kroków algorytmu, ale jednocześnie uniemożliwia zmianę jego struktury.

Definicja zaczerpnięta z książki Rusz głową! Wzorce projektowe

Schemat wzorca

„Elementy” wzorca

Wzorzec metoda szablonowa musi składać się z jednej metody, która nie może być przesłaniana w klasach podrzędnych. W javie taką metodę oznaczamy jako metodę finalną (słowo kluczowe final). Dodatkowo musimy określić metody, które będą wykonywały określone kroki algorytmu oraz możemy dodać tak zwane metody haczyki.

Metody algorytmu

Metody te wykonają operacje, które są ściśle związane z wykonywanym algorytmem. Mogą być one abstrakcyjne, ale równie dobrze mogą być one normalnymi metodami. Jeżeli dany krok algorytmu będzie jednakowy dla wszystkich klas pochodnych, to nie ma sensu oznaczania go jako abstrakcyjny, lepiej jest napisać taką metodkę już w klasie nadrzędnej, dzięki czemu będziemy mieli mniej metod, które będziemy musieli nadpisywać w klasach pochodnych. Jako metody abstrakcyjne powinniśmy oznaczać elementy, które mogą być różne w zależności od klasy pochodnej.

Metody haczyki

Metody haczyki, są to zwykłe metody, które biorą udział w wykonywanym algorytmie, jednak nie jest wymagane nadpisanie ich operacji. Chodzi o to, że metody takie mogą zmieniać zachowanie kroku algorytmu. Przykładem takiej metody w życiu codziennym jest metoda paint() w klasach pakietu Swing – metoda ta domyślnie nie ma swojego „ciała”, jednak możemy je napisać w zależności od potrzeb naszych, bądź możemy zostawić w stanie takim jakim jest i otrzymać standardową implementację algorytmu.

Budowanie domków

Dzisiaj wcielimy się w rolę właściciela firmy budującej domy od podstaw w surowym stanie (bez wykończenia). Nasza firma będzie budowała domy murowane oraz drewniane. W każdym z domów, budowa polegać będzie na wylaniu fundamentów, postawieniu ścianek oraz zrobienie dachu (nie jestem pewien, czy w domkach drewnianych wykonuje się fundamenty, ale dla tego przykładu przyjmijmy, że się to robi). Z tego krótkiego opisu można wywnioskować, że posiadamy 2 klasy – DomDrewniany oraz DomMurowany. Każda z tych klas posiada metody służące do budowania konkretnych etapów domów oraz metodę budujDom, która określa kolejne kroki, w jaki sposób powinny być takie domy budowane.

Pierwszy projekt

Jak widać na załączonym wyżej obrazku, mamy bardzo duże podwojenie kodu. Aż chce się połączyć to wszystko jakimś interfejsem albo klasą abstrakcyjną. W tym przypadku wykorzystamy klasę abstrakcyjną (jeśli ktoś chce wykonać to za pomocą interfejsów, nie widzę przeszkód, aby zrobił to we własnym zakresie 😉 Tutaj dla prostoty wykorzystamy klasy abstrakcyjne).

Implementacja wzorca

Tak wygląda nasz nowy diagram budowania domów. Jak widać, nasza klasa House jest klasą abstrakcyjną oraz posiada jedną metodę abstrakcyjną buildWalls() – służącą do stawiania ścian naszego domu. Dodatkowo metoda buildHouse() jest naszą metodą szablonową, która jest finalna, abyśmy nie mogli jej przesłonić w klasach niższych (zasada budowy domu jest zawsze taka sama, przecież nie możemy zacząć budować domu od stawiania dachu, prawda!?).

Rozszerzenie oferty

Do naszej oferty dorzuciliśmy wstawianie okien – każdemu klientowi, który złoży u nas zamówienie na wybudowanie domu, dodatkowo montujemy okna. Domyślnie montujemy zawsze okna w kolorze białym, jednak podczas stawiania domów drewnianych będziemy wstawiać okna w kolorze brązowym z drewnianą fakturą (aby lepiej pasowały do domu).

Dodanie metody haczyka

Metoda insertWindows() jest naszym haczykiem. Domyślnie wszędzie dajemy okna w kolorze białym, jednak jeśli w którejś klasie podrzędnej będziemy chcieli zamontować inne okna, wystarczy przesłonić metodę insertWindows().

Podsumowanie

Wzorca metoda szablonowa stosujemy zawsze tam, gdzie chcemy, aby pewne kroki algorytmu wykonywały się zawsze w określonej kolejności. Wzorca tego można szukać w sort() klasy Arrays w Javie. Podczas przekazywania tablicy do posortowania, musimy przekazać obiekt Comparable, na którym będzie wykorzystywana metoda compareTo(). Nie jest to może dokładna implementacja wzorca ze schematu na początku artykułu, ale nie zawsze implementuje się wzorce w postaci podawanej w książkach.

github

Przykład uruchomienia aplikacji:

public class Startup {
    public static void main(String[] args) {
        House brickHouse = new BrickHouse();
        House woodHouse = new WoodHouse();
        brickHouse.buildHouse();
        System.out.println();
        woodHouse.buildHouse();
    }
}

Wyjście:

Pouring foundations
Building bricked walls
Building roof
Inserting white windows

Pouring foundations
Building wooded walls
Building roof
Inserting brown windows