Prostředník (návrhový vzor)

Prostředník (anglicky Mediator) patří mezi návrhové vzory, které zjednodušují program. Často je použit společně s návrhovým vzorem Pozorovatel (anglicky Observer). Na rozdíl od Fasády, která ze složitého systému vybírá pouze vhodnou část, nepřidává funkcionalitu a zjednodušuje komunikaci systému směrem k dalším systémům (programům), Prostředník funkcionalitu přidává a zjednodušuje komunikace objektů v systému (uvnitř programu), kde nahrazuje vazby mezi objekty typu m:n vazbami n:1.

Princip

editovat

Jeho princip spočívá v tom, že mezi komunikující objekty je vložen další objekt (právě tento objekt je prostředníkem), někdy může být mezi komunikující objekty vloženo i několik prostředníků. Na první pohled by se mohlo zdát, že vložením prostředníka program zesložiťujeme, ale opak je pravdou, protože si objekty nemusí pamatovat odkazy na všechny ostatní objekty, ale pouze na prostředníka.


Příklad ze života

editovat

Princip tohoto návrhového vzoru je možno spatřit i v reálném životě. Například, když člověk posílá SMS zprávu. Koncovým uživatelům (objektům) se zdá, že zprávy posílají mezi sebou přímo, ale ve skutečnosti tomu tak není. Zpráva je z mobilního telefonu odesílatele poslána jeho středisku zpráv, to ji pak odešle, pokud příjemce má stejného operátora, na mobilní telefon příjemce nebo jí předá středisku zpráv operátorovi, kterého má příjemce, a ten zprávu pošle na telefon příjemce. Díky tomuto principu se odesílatel nemusí starat, jakého operátora má příjemce, nebo jestli se nenachází v zahraničí. Jelikož zprávy neposíláme přímo, tak se nemusíme znát celou "cestu" zprávy a může odesílatel nebo příjemce snadno změnit operátora a zpráva stejně dojde, dále je možné uchovávat odeslané zprávy (případně je kontrolovat, zda např. neobsahují informace k dopadení zločinců a podobně).

Příklad – vybírání jmen

editovat

Příkladem použití vzoru může být okno se seznamem pořadů, z nichž si vybíráme své oblíbené, které pak si pak můžeme vytisknout na standardním výstupu a zobrazit v informačním okně. Okno programu obsahuje dva panely, kde jsou názvy pořadů, vstupní pole pro přidávání pořadů, tlačítka pro přidání pořadu, přesunutí do oblíbených, vyčištění seznamu oblíbených a vytištění do souboru a na standardní výstup. V případě, že by nebyl zařazen do programu prostředník, tak by každý součást programu musela vědět o ostatních součástech a znát jejich metody, při použití prostředníka stačí součásti znát pouze prostředníka. Touto konstrukci se zaručí mnohem snazší budoucí úpravy programu, jelikož když změníme nějakou metodu, tak nemusíme opravovat všechny její použití, ale pouze použití u prostředníka.

Implementace příkladu v jazyce Java

editovat

Diagram tříd

editovat
 
Diagram tříd bez použití návrhového vzoru prostředník
 
Diagram tříd po aplikaci návrhového vzoru prostředník

Princip nahrazení původních vztahů m:n, lze dobře vidět z diagramu tříd. Komplikované vztahy mezi jednotlivými třídami byly nahrazeny jednoduššími vztahy jednotlivých tříd k prostředníkovi. Toto uspořádání umožňuje snadnější budoucí úpravy programu, ale klade větší nároky na prostředníka.

Rozdělení tříd

editovat

Při implementaci je vhodné si rozdělit třídy podle toho, jakým způsobem budou komunikovat s prostředníkem. Podle tohoto kritéria je možno najít 3 skupiny tříd:

  • Upozorňují prostředníka (volají metody prostředníka)
    • v našem příkladě se jedná o všechny "tlačítkové" třídy
    • při stisknutí zavolají metodu prostředníka a tím mu tlačítko oznámí, že bylo stisknuto
  • Provádějí prostředníkovy příkazy (jejich metody jsou volány prostředníkem)
    • v našem příkladě to jsou to třídy ZdrojovyList, OblibenyList a VstupniPole
    • prostředník ovlivňuje pomocí metod obsah těchto tříd
  • Komunikují obousměrně (upozorňují a provádějí příkazy)
    • jedná se konkrétně o třídu HlavniOkno

Ukázka části kódu

editovat

Ve výseku je použita část při výběru pořadu ze zdrojového listu do seznamu oblíbených, kde je vidět implementace návrhového vzoru:

  • Třída Prostrednik
/* Pro zpřehlednění je vynechána část metod, atributů a konstruktory */

/**
 * Třída Prostrednik zprostředkovává komunikaci mezi jednotlivými
 * komponentami aplikace. Integruje v sobě volání metod ostatních objektů
 * v aplikaci.
 */
public class Prostrednik {

 private ZdrojovyList zdrojovyList; //List, ve kterém jsou uloženy
 //a zobrazeny názvy pořadů.
 private OblibenyList oblibenyList;//List, do kterého jsou přidávány vybrané
 //pořady.
 
 /**
 * Metoda, která (pokud je vybrané nějaké pole ze zdrojového listu pořadů)
 * přidá vybraný pořad do listu oblíbených pořadů.
 */
 public void vybrat() {
 if (zdrojovyList.vybrano() != null) { //Musí být vybrán nějaký pořad.
 String vybrano = zdrojovyList.vybrano(); //Získání vybraného textu.
 oblibenyList.pridej(vybrano); //Vybraný text je přidán do oblíbeného
 //listu pořadů.
 zdrojovyList.odeber(vybrano); //Vybraný text je odebrán
 //ze zdrojového listu.
 zdrojovyList.vycisti(); //Výběr ve zdrojovém listu je vynulován.
 }
 }
}
  • Třída VybratTlacitko
/**
 * Třída VybratTlacitko slouží k oznámení, že nějaký pořad chce uživatel přidat
 * mezi oblíbené pořady. Třída není závislá na tom odkud se má vybírat ani kam
 * se má přidávat, to vše zařizuje prostředník.
 */
public class VybratTlacitko extends JButton {

 private Prostrednik prostrednik;

 /**
 * Konstruktor vytvářející tlačítka s názvem Vyber. Při vytváření si uloží
 * odkaz na prostředníka, kterému pak dává vědět, že bylo stisknuto.
 *
 * @param prostrednik prostředník, kterému má dávat vědět, že bylo stisknuto
 */
 public VybratTlacitko(Prostrednik prostrednik) {
 super("Vyber");
 this.prostrednik = prostrednik;
 addActionListener(new Posluchac());//Přidání posluchače, který poslouchá
 //zda bylo tlačítko stisknuto.
 }

 /**
 * Vnořená třída implementující rozhraní ActionListener sloužící jako
 * posluchač tlačítka a kdykoliv je tlačítko stisknuto, tak o tom informuje
 * prostředníka.
 */
 private class Posluchac implements ActionListener {

 /**
 * Implementovaná metoda, která je spuštěna, když nastane určitá událost
 * (tlačítko bylo stisknuté).
 * Je oznámeno prostředníkovi pomocí volání metody, že nastala tato
 * událost (stisknutí tlačítka), která pak zpracuje zbytek.
 */
 public void actionPerformed(ActionEvent e) {
 prostrednik.vybrat();//Oznámení prostředníkovi, že bylo stisknuto
 //tlačítko vybrat.
 }
 }
}
  • Třída OblibenyList
/**
 * Třída OblibenyList slouží k zobrazení, evidenci a získání seznamu pořadů.
 * Není závislá na zdroji pořadů ani na výstupu, kam se má seznam vytisknout,
 * tyto funkcionality zabezpečuje prostředník, čímž je zaručena snadná
 * modifikace aplikace.
 */
public class OblibenyList extends JList {

 /**
 * Metoda, která přidá zadaný název pořadu mezi oblíbené pořady.
 *
 * @param nazev název pořadu, který se přidává
 */
 public void pridej(String nazev) {
 listModel.addElement(nazev);
 }
}
  • Třída ZdrojovyList
/**
 * Třída ZdrojovyList slouží k zobrazení seznamu názvů pořadů a získávání názvu
 * vybraného pořadu. Dále je možno do listu přidávat a odebírat názvy pořadů
 * nebo je odebrat všechny. O tom jaká činnost bude prováděna rozhoduje
 * prostředník.
 */
public class ZdrojovyList extends JList {

 private DefaultListModel listModel;//Výchozí model pro uložení/zobrazení
 //dat v seznamu.
 //Výchozí názvy pořadů.
 private static final String[] PORADY = {"Přátelé", "HIMYM"};

 /**
 * Metoda, která vrátí vybraný pořad nebo null pokud nebyl žádný pořad
 * vybrán.
 *
 * @return vybraný pořad ze zdrojového listu nebo null, když nebylo nic
 * vybráno
 */
 public String vybrano() {
 return getSelectedValue();
 }

 /**
 * Metoda odebere zadaný text ze seznamu pořadů.
 *
 * @param odebirany text, který se má odebrat
 */
 public void odeber(String odebirany) {
 listModel.removeElement(odebirany);
 }

 /**
 * Metoda, která zruší výběr v listu. List bude nastaven do pozice, jako by na něm
 * nebylo kliknuto.
 */
 public void vycisti() {
 clearSelection();
 }
}

Příbuzné vzory

editovat

Při aplikaci návrhového vzoru prostředník se často používá návrhový vzor Pozorovatel pro oznámení změny stavu programu, jeho dalším částem.[1]

Závěr

editovat

Návrhový vzor Prostředník je vhodné použít pokud jsou vnitřní vztahy v systému příliš složité a nepřehledné. Zavedením prostředníka se výrazně zvýší přehlednost systému a usnadní budoucí změny systému. Také je možné prostředníka nahradit jiným a tím jednoduše změnit funkčnost celého systému.

Literatura

editovat

Externí odkazy

editovat