Návrhový vzor Template se používá v případě, že existuje nějaký algoritmus s volitelnými kroky a my chceme, aby všechny potenciální podtřídy mohly požadované kroky algoritmu implementovat jinak bez nutnosti zasahovat do původního algoritmu.

Řešení

Třídu obsahující algoritmus nazveme Template.

Každý krok algoritmu bude reprezentován voláním jedné metody. Tato metoda může obsahovat nějakou rozumnou výchozí implementaci (pokud taková existuje), nebo může být deklarována jako abstraktní, aby byly podtřídy k její implementaci donuceny. Potom již zbývá jen implementovat potřebné podtřídy a implementovat či překrýt potřebné kroky.

diagram tříd (UML)

Varianty

  • základní třída se šablonou může obsahovat výchozí implementaci některých kroků a podtřídy mění jen ty, které nevyhovují
  • jedna třída může obsahovat více šablon
  • jednotlivé kroky mohou být skryté či veřejné
  • podtřída může změnit i pořadí kroků

Související vzory

  • Strategy - jednotlivé metody volané v šabloně jsou zapouzdřeny v samostatné třídě
  • Factory Method - speciální a celkem častý typ šablonové metody pro vytváření objektů

Příklad

Osoba

Náš příklad bude představovat osobu a její denní činnosti. Konkrétní zaměstnání bude implementováno jako potomek této třídy.

package gof.template;

public abstract class Person {
    public void printDailyRoutine() {
        // this is a template method
        wake();
        work();
        relax();
        sleep();
    }

    abstract protected void wake();

    abstract protected void work();

    abstract protected void relax();

    abstract protected void sleep();
}

Zdrojový kód Pokrytí testy

Zaměstnanec

package gof.template;

public class Worker extends Person {
    protected void wake() {
        System.out.println("Waking up at 6:00.");
    }

    protected void work() {
        System.out.println("Going to work. Working...");
    }

    protected void relax() {
        System.out.println("Watching stupid movies.");
    }

    protected void sleep() {
        System.out.println("Going to bed.");
    }
}

Zdrojový kód Pokrytí testy

Dítě

package gof.template;

public class Child extends Person {
    protected void wake() {
        System.out.println("Waking up at 7:00.");
    }

    protected void work() {
        System.out.println("Going to school.");
    }

    protected void relax() {
        System.out.println("Playing with other kids.");
    }

    protected void sleep() {
        System.out.println("Going to bed.");
    }
}

Zdrojový kód Pokrytí testy

Použití

package gof.template;

import org.junit.Test;

public class Example {
    @Test
    public void testWorker() {
        final Person worker = new Worker();
        worker.printDailyRoutine();

        // -- prints --
        // Waking up at 6:00.
        // Going to work. Working...
        // Watching stupid movies.
        // Going to bed.
    }

    @Test
    public void testChild() {
        final Person child = new Child();
        child.printDailyRoutine();

        // -- prints --
        // Waking up at 7:00.
        // Going to school.
        // Playing with other kids.
        // Going to bed.
    }
}

Zdrojový kód Pokrytí testy

Reference