Facade [f ə ˈ s ɑː d]f ə ˈ s ɑː d
Facade Před: Po:
Facade Subsystémy (Zordi)Fasáda (Megazord)
Facade Známý jako Facade, Fasáda Motivace Rozdělení systému na subsystémy Subsystém = množina tříd a dalších subsystémů Rozhraní subsystému se s přibývajícíma třídami stává složitým Řešením je zavedení fasády - sjednocené high-level rozhraní Řada užitečných vlastností Zapouzdření – uživatel nemusí pracovat přímo se třídami subsystému Použití subsystémů je zjednodušeno Redukce závislosti mezi subsystémy Zjednodušuje komunikaci subsystémů Decoupling Zvyšuje přenositelnost …
Facade – domácí kino projektor DVD přehrávač žaluzie HI-FI soustava Puštění filmu: zatáhnutí žaluzií zapnutí projektoru zapnutí DVD přehrávače zapnutí ozvučení Ukončení přehrávání: vypnout DVD přehrávač vypnout ozvučení vypnout projektor vytáhnout žaluzie
Facade – domácí kino Řešení: Univerzální ovladač s funkcemi: Přehrát film Ukončit film … zatáhnout žaluzie zapnout projektor zapnout DVD přehrávač zapnout ozvučení vypnout DVD přehrávač vypnout ozvučení vypnout projektor vytáhnout žaluzie
Facade – kompilátor Účastníci Fasáda – Compiler Přijímá high-level požadavky Deleguje požadavky klienta mezi třídy subsystému Může vykonávat vlastní práci (napr. Adapter)
Facade – kompilátor Účastníci Subsystémy – Scanner, Parser, … Implementují logickou část kompilátoru Vykonávají příchozí požadavky od fasády O fasádě nevědí (transparentnost) Nejsou skryté (!)
Facade – kompilátor class Scanner { public: … Scanner(istream&); virtual Token& Scan(); … }; Třída subsystému class Parser { public: … virtual void Parse(Scanner&, ProgramNodeBuilder&); … }; Třída subsystému class ProgramNodeBuilder { public: ProgramNodeBuilder(); virtual ProgramNode* NewVariable(…); virtual ProgramNode* NewAssignment(…); virtual ProgramNode* NewReturnStatement(…); virtual ProgramNode* NewCondition(…) const; … ProgramNode* GetRootNode(); … }; Třída subsystému
Facade – kompilátor class ProgramNode { public: // program node manipulation virtual void GetSourcePosition(int& line, int& index); … // child manipulation virtual void Add(ProgramNode*); virtual void Remove(ProgramNode*); … virtual void Traverse(CodeGenerator&); protected: ProgramNode(); }; Třída subsystému void ExpressionNode::Traverse (CodeGenerator& cg) { cg.Visit(this); ListIterator i(_children); for (i.First(); !i.IsDone(); i.Next()) { i.CurrentItem()->Traverse(cg); }
Facade – kompilátor class Compiler { public: Compiler(); virtual void Compile(istream&,BytecodeStream&); }; void Compiler::Compile ( istream& input, BytecodeStream& output ) { Scanner scanner(input); ProgramNodeBuilder builder; Parser parser; parser.Parse(scanner, builder); RISCCodeGenerator generator(output); // potomek CodeGenerator ProgramNode* parseTree = builder.GetRootNode(); parseTree->Traverse(generator); } Facade class CodeGenerator { public: virtual void Visit(StatementNode*); virtual void Visit(ExpressionNode*); … protected: CodeGenerator(BytecodeStream&); protected: BytecodeStream& _output; }; Třída subsystému
Facade – volání funkce Diagram volání funkce Uživatel využívá Facade pro přístupu k systému
Facade – reálná implementace Systém kombinující info o letech a hotelech
Použití Když je subsystém složitý na přímé použití Cena za vytvoření fasády < nastudování subsystému uživateli Umožnuje obalit množinu špatně navržených API do jednoho lepšího Když existuje mnoho závislostí vně subsystému/mezi subsystémy Komunikace skrz fasádu (higher-level interface) Při vytváření vstupních bodů vrstveného systému Výhody použití Redukuje počet objektů, se kterými klienti komunikují Snadnější použití subsystému Snadnější nahrazení částí subsystému a rozšíření subsystému Zmenšuje počet závislostí mezi klienty a subsystémem Odstraňuje komplexní a kruhové závislosti Méně kompilačních závislostí Neskrývá třídy subsystému Jednoduchost nebo použití na „míru“ Facade – použití
Facade – implementace Fasáda jako abstraktní třída (příp. interface) Konkrétní implementace pro konkrétní subsystém je jejím potomkem Klienti komunikují se subsystémem přes rozhraní abstraktní třídy Klient nemusí vědět, která implementace byla použita Flexibilita Fasáda jako jedna konfigurovatelná třída Slabší alternativa Výměna komponent subsystému za běhu Dependency Injection, Inversion of Control
Typické chyby Fasáda vůbec nebyla zapotřebí Subsystém je příliš jednoduchý Fasáda byla implementována už od začátku Má přibýt až když je potřebná Uživatel je nucen fasádu používat Třídy subsystému jsou privátní Fasáda neslouží k zvýšení bezpečnosti Nic neskrývá Subsystém o fasádě ví Třídy subsystému si drží referenci na fasádu Fasáda implementuje více než by měla Facade – použití
V mobilních aplikacích OS jako Façade Interface pro ovládání přístoje Session Façade, Core J2EE Patterns Fasáda pro webové služby JOptionPane ve Swingu vytváří a zobrazuje různé typy základních dialogových oken zjednodušuje používání této rozsáhlé knihovny Tomcat a jeho servlet API Facade – reálné použití
Facade – související vzory Abstract Factory Fasáda může poskytovat rozhraní pro tvorbu objektů Singleton Fasáda jako Singleton - jen jeden vstupní bod do systému Adapter Adapter také tvoří interface pro přístup k systému Nadstavba nad existujícími rozhraními Primární funkci – standardizovat rozhraní Mediator Mediator také snižuje závislosti Komponenty subsystému přes něj komunikují (vědí o něm!) Mediator abstrahuje funkcionalitu ze tříd a sám ji implementuje
Facade – shrnutí (aneb výhody po třetí) Poskytuje zjednodušené rozhraní Komfort uživatele je priorita Ale neskrývá ani původní rozhraní Zapouzdřuje subsystém Množina špatně navržených API alternována jediným dobře navrhnutým API Eliminuje závislosti všeho druhu Klient – subsystém Subsystém – subsystém Mezi dvěma třídami subsystému Ve výsledku eliminuje i kompilační závislosti …