Mediator
Návrhový vzor Mediator zavádza "sprostredkovateľa" medzi priamu komunikáciu viacerých objektov. Tým znižuje počet väzieb medzi objektmi a reguluje ich zodpovednosť. Jedná sa o veľmi populárny princíp, ktorý využíva aj vzor Controller zo sady vzorov GRASPO, prípadne vzor inDirection rovnako z GRASPO.
Motivácia
Hoci to znie možno paradoxne, pridaním "umelé" triedy môžeme často našu aplikáciu zjednodušiť. Ak spolu nejaká množina objektov komunikuje priamo, vzniká zbytočné množstvo zložitých väzieb medzi nimi. Pokiaľ bude množina objektov komunikovať iba s mediátorom a on s nimi, zníži sa počet týchto väzieb. Ukážme si, ako by mohla vyzerať situácia, keby spolu nejaké komponenty komunikovali priamo:
Množstvo väzieb medzi komponentmi je vysoké, porušujeme low coupling a komponenty na sebe navzájom závisia. Teraz skúsme zaviesť prostredníka, ktorý bude všetku komunikáciu sprostredkovávať:
Mediátor takisto zníži potrebu presnej znalosti objektov medzi sebou a kód sa zjednoduší. Stačí, keď objekt vie komunikovať len s mediátorom. O nič ďalšie sa nemusí starať. Komunikačné mechanizmus medzi objektmi potom zostane zapuzdrený na jednom mieste, v mediátora. Objekty možno takto samozrejme aj jednoducho meniť bez nutnosti úpravy všetkých ďalších účastníkov interakcie.
V praxi sa mediátor často používa napr. Pre komunikáciu medzi formulárovými prvkami. Zabránime tým, aby sa na seba museli formulárové prvky navzájom odkazovať, budú komunikovať s mediátorom, samostatným objektom, ktorý bude podľa aktuálnych akcií upravovať stav formulára.
Vzor
Vzor Mediator zavádza niekoľko pojmov:
Mediator
- Pre mediátor definuje abstraktné triedu. Konkrétnych mediátorov môže byť potom viac.Colleague
- Abstraktné triedu potom definuje tiež pre kolegov, objekty v interakcii. Vďaka abstraktné triede môžu konkrétne kolegovia rovno jednoducho zdediť väzbu na mediátor.ConcreteColleague
... - Konkrétne objekty implementujú ľubovoľné operácie a majú väzbu na mediátor.ConcreteMediator
... - Konkrétne mediátormi udržujú väzbu na všetkých kolegov, aby mohli komunikáciu sprostredkovávať.
Príklad
Pomerne klasickým príkladom pre použitie vzoru je vytvorenie mediátora pre rôzne typy loggerov. Aplikácia potom nekomunikuje s niekoľkými loggery, ale s jedným mediátorom, ktorý podľa metód a parametrov sprostredkováva komunikáciu na loggery. Toto použitie mediátora je veľmi podobné fasádam, avšak s tým rozdielom, že fasáda často iba deleguje na rozhraní nejaké už existujúce implementácie, zatiaľ čo prostredník v sebe obsahuje logiku, kód potrebný pre sprostredkovanie komunikácie.
Taký zložený mediátor pre logovanie by mohol vyzerať napr. Nasledovne:
public class LoggerMediator { private TypLogovani typLogovani; private FileLogger fileLogger = new FileLogger(); public void setTypLogovani(TypLogovani typLogovani) { this.typLogovani = typLogovani; } public void loguj(String zprava, Level level) { if (typLogovani == TypLogovani.Konzole) { if (level == Level.Error) System.err.println(zprava); else System.out.println(zprava); } else if (typLogovani == TypLogovani.Soubor) { if (level == Level.Error) fileLogger.log(zprava, FileLogger.ERROR); else fileLogger.log(zprava, FileLogger.DEBUG); } } }
Mediátor pomocou nejakej vnútornej logiky deleguje logovanie na rôzne loggery. Ukážme si ešte rozdiel oproti fasáde nad loggery, ktorá by rozhranie iba delegovala:
public class LoggerFacade { public void logInfo(final String zprava) { System.out.println(zprava); } public void logError(final String zprava) { System.err.println(zprava); } }
Súvisiace vzory
- Fasáda - Delegovanie funkcionality pomocou jednoduchého rozhrania na skupinu ďalších objektov