Template method slouží k definování kostry obecného algoritmu, aniž bychom znali jeho konkrétní kroky. Tuto kostru posléze můžeme použít pro implementaci jednotlivých specifických algoritmů z ní vycházejících.
Jádrem vzoru je abstraktní třída specifikující kostru algoritmu (obecný postup), která využívá abstraktních metod tatktéž definovaných v této třídě. Děděním a specifikací těchto abstraktních metod dojde k doplnění šablony na plnohodnotný algoritmus. Výhodou tohoto postupu je neopakování kostry v každé specifikaci a snadná zaměnitelnost specifikací prostřednictvím abstraktního předka.
Příklad
Implementací tohoto vzoru je algoritmus pro vaření polévek. Polévky se dělají velmi podobným zůsobem - upravíme suroviny, přidáme je do hrnce s vodou a vaříme, dokud není hotovo. To je kostra algoritmu, specifické metody definují, co to znamená upravit suroviny, kdy je hotovo atp.
/**
* Template pro vareni polevky
* @author Pavel Micka
*/
abstract class AbstractCookSoupAlgorithm{
/**
* Kostra algoritmu - template method
* @return polevka
*/
public String cookSoup(){
String[] ingredients = getIngredients();
prepareIngredients(ingredients);
addWater();
while(!finished()){
boil();
}
System.out.println("Polevka je uvarena");
return "Uvarena polevka";
}
/**
* Suroviny do polevky
* @return suroviny
*/
protected abstract String[] getIngredients();
/**
* Pripravi suroviny
* @param ingredients suroviny
*/
protected abstract void prepareIngredients(String[] ingredients);
/**
* Je polevka hotova
* @return @true pokud je uvareno, @false pokud neni uvareno
*/
protected abstract boolean finished();
/**
* Prida vodu do polevky
*/
protected abstract void addWater();
/**
* Vari polevku
*/
protected abstract void boil();
}
class CookInstantSoupAlgorithm extends AbstractCookSoupAlgorithm{
@Override
protected String[] getIngredients() {
return new String[]{"Sacek instantni gulasove polevky"};
}
@Override
protected void prepareIngredients(String[] ingredients) {
System.out.println("Oteviram sacek");
}
@Override
protected boolean finished() {
//bud 0 nebo jedna
Random r = new Random(System.currentTimeMillis());
if(r.nextInt(2) == 0) return true; //zelenina je mekka, uvareno
return false;
}
@Override
protected void addWater() {
System.out.println("Pridavam hrnek varici vody");
}
@Override
protected void boil() {
//nic nedelame, protoze se hrnickova polevka nevari
}
}
class CookVegetableSoupAlgorithm extends AbstractCookSoupAlgorithm{
@Override
protected String[] getIngredients() {
return new String[]{"mrkev, celer, petrzel, 2x slepisi bujon, cibule, cesnek, brambory"};
}
@Override
protected void prepareIngredients(String[] ingredients) {
for(String ingredient : ingredients){
System.out.println("Krajim " + ingredient);
}
}
@Override
protected boolean finished() {
//bud 0 az 4
Random r = new Random(System.currentTimeMillis());
if(r.nextInt(5) == 0) return true;
return false;
}
@Override
protected void addWater() {
System.out.println("Pridavam 2 litry vody");
}
@Override
protected void boil() {
System.out.println("Varim na strednim plamenu");
}
}
Literatura
- PECINOVSKÝ, Rudolf. Návrhové vzory. 1. vyd. [s.l.] : Computer press, 2007. 527 s. ISBN 978-80-2511582-4.