Po tom, co jsme si v minulém díle seriálu vysvětlili princip návrhových vzorů, se nyní podíváme na další dva z našeho výběru. Tentokrát to bude static factory method (statická tovární metoda) a servant (služebník).
Jelikož už víme, co to návrhové vzory jsou, nebudeme dlouho chodit kolem horké kaše a rovnou se podíváme na další dva zástupce.
Static factory method (statická tovární metoda)
Static factory method je návrhový vzor, který použijeme většinou při práci v týmech na rozsáhlých projektech. Není to samozřejmě podmínkou. Je založen na principu privátního konstruktoru, ke kterému se tedy přímo nepřistupuje, nýbrž volá se prostřednictvím statických metod.
Na první pohled zbytečná složitost však ve výsledku přinese mnoho dobrého. První (estetickou) výhodou je, že metodu si můžeme pojmenovat (na rozdíl od konstruktoru) jak chceme, což přináší jisté zlepšení přehlednosti. Druhou výhodou (a kvůli tomu se tento vzor používá) je napsání statických metod přesně podle logických požadavků navrhovaného systému. Vrhněme se nyní na ukázku, která nám vše vysvětlí.
Mějme firemní systém, který bude evidovat domy. Domy mají spoustu různých vlastností (budou to tedy instanční atributy), ale naše fiktivní firma má v evidenci pouze jednopatrové a dvoupatrové domy. Budeme-li tedy vytvářet instanci domu, nejprve rozhodneme, jestli bude náš dům jednopatrový či dvoupatrový a ostatní atributy budou nastaveny dále, individuálně.
class Dum { /* * Definice různých atributů. */ private final int pocetPoschodi; private Dum(int pocetPoschodi){ this.pocetPoschodi = pocetPoschodi; } public static Dum getJednoposchodovyDum(){ return new Dum(1); } public static Dum getDvouposchodovyDum(){ return new Dum(2); } }
public class Domy { public static void main(String[] args) { Dum prvni = Dum.getJednoposchodovyDum(); /* * Další práce s jednoposchoďovým domem. */ } }
Jakožto autoři této třídy jsme tedy jednoduše ošetřili, aby autoři jiných tříd, které tuto využívají, nevytvářeli sedmiposchoďové domy. K čemu by to také bylo? Logicky, vždyť firma se zabývá pouze jednopatrovými a dvoupatrovými - nemá smysl brát v úvahu jiné varianty.
Servant (služebník)
Návrhový vzor Servant je vzor, který se používá k přidání funkce určité množině třídy bez zásahu do jejich kódu tak, abychom se vyhnuli opakování stejného nebo podobného kódu.
Mezi servantem a obsluhovanými musí existovat jakási dohoda, určující co mají obsluhované třídy umět. To v praxi provedeme samozřejmě použitím rozhraní, které implementují všechny třídy využívající servanta. Metodám tohoto servanta pak jako parametr předáváme objekt, který má implementované právě toto rozhraní. Ukážeme si na příkladě.
Mějme dvě skupiny osob, muže a ženy. Zástupci obou skupin mají hmotnost a výšku, jsou tedy měřitelní. Využijeme servanta k tomu, aby díky vědomí, že každý, kdo je měřitelný, počítal BMI. Jedinou otázkou je, jak takového „jednoduchého“ servanta pojmenovat. Pro náš ukázkový případ, kdy servant pracuje s měřitelnými objekty (tedy implementujícími rozhraní IMeritelny), ho nazveme například Měřič. Název je vskutku celkem důležitý, jelikož v rozsáhlejších systémech se servantů běžně používá několik, a tak pojmenování "Servant" není úplně vhodné.
interface IMeritelny {
public double getVyska();
public double getVaha();
}
class Zena implements IMeritelny {
private double vaha;
private double vyska;
@Override
public double getVaha() {
return vaha;
}
@Override
public double getVyska() {
return vyska;
}
}
class Muz implements IMeritelny {
private double vaha;
private double vyska;
@Override
public double getVaha() {
return vaha;
}
@Override
public double getVyska() {
return vyska;
}
}
class Meric {
public double BMI(IMeritelny objekt) {
double bmi = objekt.getVaha() / (objekt.getVyska() * objekt.getVyska());
return bmi;
}
}
public class UkazkaServant {
public static void main(String[] args) {
Zena z = new Zena();
Muz m = new Muz();
Meric meric = new Meric();
double bmiZeny = meric.BMI(z);
double bmiMuze = meric.BMI(m);
}
}
Nutno podotknout, že tato ukázka je velmi krajní případ. Muž a žena by museli mít mnoho a velmi odlišných vlastností, abychom je vůbec definovali jako dvě různé třídy namísto jedné. Jde mi však o důvod a způsob použití tohoto návrhového vzoru a to je z toho, myslím, jasně vidět.
Závěrem
Doufám, že jsem vám tímto dílem seriálu pomohl osvětlit další zákoutí labyrintu návrhových vzorů. Máte-li k nim jakékoliv otázky, neváhejte se ptát v komentářích.