Fasáda (návrhový vzor)
Fasáda (anglicky Facade) je softwarový návrhový vzor, který slouží ke zjednodušení komunikace mezi uživatelem a systémem. Použití je výhodné, pokud je tento systém příliš komplexní (obsahuje mnoho tříd a vazeb) pro splnění dané oblasti úloh, jež po něm vyžadují uživatelé. Fasáda je způsob nahrazení velkého počtu rozhraní subsystémů, sjednoceným rozhraním, které bude zaštitovat všechna rozhraní subsystémů. Cílem je tedy omezit množství tříd, se kterými musí uživatel komunikovat. Často se využívá spolu s návrhovým vzorem jedináček (Singleton). Fasáda nemusí být realizována jako jediná třída, ale může být i skupinou tříd.[1][2]
Účel
Při využívání komplexního systému pro relativně jednoduché úlohy je výhodné vytvořit vrstvu mezi samotným systémem a vlastními třídami, což má za následek zjednodušení používání tohoto systému a dále jeho „schování“ za fasádu. Vedlejším efektem fasády je poté možnost změnit systém, bez ohledu na uživatelovy třídy, které komunikují pouze s prostředníkem, tedy fasádou. Ukázka jednoduchého diagramu bez použití fasády je na obrázku č. 1 a s použitím na obrázku č. 2.
Účel fasády lze shrnout, jak píše Pecinovský: „Účelem fasády je umožnit uživatelům s jednoduššími požadavky pracovat se složitým systémem, jako by byl jednoduchý.“[1]
Kdy použít
Ne vždy je vhodné tento návrhový vzor použít, a proto je uveden výčet typických situací, kdy by se použít měl.
- Chceme-li ke komplexnímu systému nabídnout zjednodušené rozhraní – Systém se skládá ze subsystémů, které se stávají složitějšími v průběhu vývoje. Často jsou tyto subsystémy rozděleny na mnoho tříd, dle principu jedné odpovědnosti (Single responsibility), tím však kromě snadně upravitelného a znovupoužitelného kódu vzniká mnoho vazeb a závislostí mezi třídami. Fasáda poté nabízí jednotný vstup pro běžné uživatele, nicméně pokud vyžadují uživatelé více, než jim fasáda nabídne, musí znát i prostředí za fasádou.[2]
- Existuje-li příliš mnoho závislostí mezi uživatelem a implementačními třídami – Vložením prvku, který zprostředkovává komunikaci mezi vnitřním a vnějším systémem je vytvořena nezávislost mezi uživatelskými třídami a třídami systému. Kompletní nezávislost je pouze za předpokladu, že fasáda poskytuje dostatečnou funkcionalitu pro všechny své uživatele a není ji třeba obcházet.[2]
- Chceme-li systém uspořádat do vrstev – Pro každou vrstvu je vytvořena fasáda, která může být považována jako vstup do subsystému. Pokud jsou na sobě různé subsystémy závislé, lze snížit jejich závislost tím, že jednotlivé subsystémy budou pro komunikaci využívat pouze fasády ostatních subsystémů.[2]
Implementace
Při implementaci je důležité brát v úvahu i přístupnost rozhraní subsystému. Stejně jako u tříd, kde mohou být veřejné i privátní atributy a metody (funkce) lze v některých objektových jazycích (např. C++, viz jmenné prostory) definovat i veřejnost, či privátnost tříd samotných. Veřejné rozhraní subsystému jsou všechny třídy, ke kterým mohou přistupovat všichni klienti, zatímco privátní rozhraní je pouze pro další subsystémy, které rozšiřují funkcionalitu. Fasáda je poté součástí veřejného rozhraní.[1]
Pro větší oddělení závislosti mezi klienty a subsystémem lze Fasádu učinit abstraktní třídou a vytvoří se podtřídy pro konkrétní implementaci. Klienti posílají zprávy přes abstraktní fasádu a neví tak, která konkrétní implementace je obsluhuje. Podtřídy není nutné vytvářet, pokud je možné objekt Fasády nakonfigurovat pomocí existujících tříd v subsystému.[1]
Rozdělení funkcí [2]:
- Fasáda
- Nabízí funkcionalitu
- Má vazby na třídy subsystému a zná jejich zodpovědnosti vzhledem k funkcionalitě (která třída odpovídá na který dotaz od uživatele)
- Deleguje dotazy od uživatele na třídy subsystému, které jsou za ně odpovědné
- Třídy v subsystému
- Neudržují odkaz na fasádu
- Implementují konkrétní funkce
- Zodpovídají dotazy delegované fasádou
Příklad implementace fasády v JAVA.
Příklad jak jednoduše vytvořit dialogové okno pomocí fasády JOptionPane v JAVA. To samé lze vytvořit také bez využití fasády a použitím přímo třídy subsystému, tou by byla v tomto případě JFrame.
...
JButton tlacitko = new JButton("Zobraz chybu");
tlacitko.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Kliknuli jste na tlačítko: Zobraz chybu", "Chyba!", JOptionPane.ERROR_MESSAGE);
}
});
...
Druhý příklad je bez využití fasády, kdy přímo přistupujeme k třídám subsystému (JFrame).
…
// Vytvořme okno, které reprezentuje Dialogové okno z předchozího příkladu
JFrame hlavniOkno = new JFrame("Chyba!");
frame.setSize(500, 250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
// Naplňme jej nějakým obsahem, např. chybovým hlášením
JLabel label = new JLabel("Chybové hlášení");
// Umístíme JLabel do vytvořeného okna
frame.getContentPane().add(label, BorderLayout.CENTER);
…
Jak je vidět z ukázky, JOptionPane nabídne pro vytváření dialogu mnohem jednodušší rozhraní, než kdybychom ho měli vytvářet sami.
Příbuzné vzory
Fasádu lze nahradit v některých případech abstraktní továrnou, popř. použít společně pro subsystémovou nezávislost, neboť abstraktní továrna kromě skrývání implementace přidává i skrývání konkrétních tříd při vytváření objektů.[1]
Podobným návrhovým vzorem je i Prostředník, který taktéž poskytuje abstraktní vrstvu mezi implementací a klientem, ale rozdílem je, že u Prostředníka klient zná třídu, se kterou komunikuje, ale používá k tomu prostředníka. Zatímco u Fasády je implementace skryta. Navíc Prostředník často přidává novou funkcionalitu, což není u Fasády běžné.[1]
Shrnutí
Cílem použití návrhového vzoru fasáda je zjednodušení rozhraní komplexního systému, tedy snížit počet tříd, se kterými musí uživatel komunikovat. Podmínkou pro použití je poměr mezi náklady na pochopení komplexního systému uživateli a vytvoření fasády.[1]
Fasáda často obsahuje pouze podmnožinu funkcí, které nabízí systém za ní, a proto se vyplatí, pokud uživatelé mají pouze relativně malé požadavky na systém.[1]
Implementačně je realizována jako jedna nebo skupina tříd, které mohou kromě funkcionality systému i přidat dodatečnou funkcionalitu. Zároveň slouží pro zapouzdření komplexního systému.[1]
Reference
- PECINOVSKÝ, Rudolf. Návrhové vzory:33 vzorových postupů pro objektové programování. 1. vyd. [s.l.]: Computer Press, 2007. 528 s. ISBN 9788025115824. S. 255–260.
- GAMMA, Erich; HELM, Richard; JOHNSON, Ralph. Návrh programů pomocí vzorů:Stavební kameny objektově orientovaných programů. 1. vyd. [s.l.]: Grada, 2003. 388 s. ISBN 8024703025. S. 185–193.