Návštevný vzor v Jave

1. Prehľad

V tomto tutoriáli predstavíme jeden z návrhových vzorov správania GoF - návštevník.

Najskôr vysvetlíme jeho účel a problém, ktorý sa snaží vyriešiť.

Ďalej sa pozrieme na UML diagram návštevníka a implementáciu praktického príkladu.

2. Dizajnový vzor návštevníka

Účelom vzoru návštevník je definovať novú operáciu bez zavedenia úprav existujúcej objektovej štruktúry.

Predstavte si, že máme a zloženýobjekt, ktorý sa skladá z komponentov. Štruktúra objektu je pevná - buď to nemôžeme zmeniť, alebo neplánujeme do štruktúry pridávať nové typy prvkov.

Ako by sme teraz mohli do nášho kódu pridať novú funkčnosť bez úpravy existujúcich tried?

Odpoveďou môže byť návrhový vzor Návštevník. Jednoducho povedané, budeme musieť urobiť, je pridať funkciu, ktorá akceptuje triedu návštevníkov pre každý prvok štruktúry.

Naše komponenty tak umožnia implementácii návštevníka ich „navštíviť“ a vykonať s daným prvkom všetky potrebné kroky.

Inými slovami, z tried extrahujeme algoritmus, ktorý sa použije na štruktúru objektov.

V dôsledku toho dobre využijeme princíp otvorenia / zatvorenia pretože nebudeme upravovať kód, ale stále budeme môcť rozšíriť funkčnosť poskytnutím nového Návštevník implementácia.

3. Diagram UML

Na vyššie uvedenom diagrame UML máme dve implementačné hierarchie, špecializovaných návštevníkov a konkrétne prvky.

Najskôr klient použije implementáciu Visitor a aplikuje ju na štruktúru objektu. Kompozitný objekt iteruje cez svoje komponenty a na každého z nich aplikuje návštevníka.

Teraz je to obzvlášť dôležité betónové prvky (ConcreteElementA a ConcreteElementB) prijímajú a Návštevník, jednoducho to umožňuje navštíviť ich.

Nakoniec je táto metóda rovnaká pre všetky prvky v štruktúre, vykonáva dvojité odoslanie s odovzdaním sama (cez toto kľúčové slovo) na metódu návštevy návštevníka.

4. Implementácia

Náš príklad bude obyčajný Dokument objekt, ktorý sa skladá z konkrétnych prvkov JSON a XML; prvky majú spoločnú abstraktnú nadtriedu, Element.

The Dokument trieda:

verejná trieda Dokument rozširuje Element {List elements = new ArrayList (); // ... @Override public void accept (Visitor v) {for (Element e: this.elements) {e.accept (v); }}}

The Element trieda má abstraktnú metódu, ktorá akceptuje Návštevník rozhranie:

public abstract void accept (Visitor v);

Pri vytváraní nového prvku ho preto pomenujte JsonElement, budeme musieť zabezpečiť implementáciu tejto metódy.

Avšak vzhľadom na povahu vzoru návštevníkov bude implementácia rovnaká, takže vo väčšine prípadov by bolo potrebné, aby sme kópiu vložili z pôvodného prvku z iného, ​​už existujúceho prvku:

public class JsonElement extends Element {// ... public void accept (Visitor v) {v.visit (this); }}

Pretože naše prvky umožňujú ich návštevu ktorýmkoľvek návštevníkom, povedzme, že chceme spracovať tie naše Dokument prvkov, ale každý z nich iným spôsobom, v závislosti od typu svojej triedy.

Preto bude mať náš návštevník pre daný typ samostatnú metódu:

public class ElementVisitor implementuje Visitor {@Override public void visit (XmlElement xe) {System.out.println ("spracovanie prvku XML pomocou uuid:" + xe.uuid); } @Override public void visit (JsonElement je) {System.out.println ("spracovanie prvku JSON s uuid:" + je.uuid); }}

Náš konkrétny návštevník tu implementuje dve metódy, jednu pre každý typ Element.

Získate tak prístup ku konkrétnemu objektu štruktúry, na ktorom môžeme vykonávať potrebné činnosti.

5. Testovanie

Na účely testovania sa pozrime na VisitorDemotrieda:

public class VisitorDemo {public static void main (String [] args) {Visitor v = new ElementVisitor (); Dokument d = nový dokument (generateUuid ()); d.elements.add (nový JsonElement (generateUuid ())); d.elements.add (nový JsonElement (generateUuid ())); d.elements.add (nový XmlElement (generateUuid ())); d.prijatie (v); } // ...}

Najskôr vytvoríme ElementNávštevník, má algoritmus, ktorý použijeme na naše prvky.

Ďalej sme nastavili náš Dokument s príslušnými komponentmi a aplikovať návštevníka, ktorého prijme každý prvok štruktúry objektu.

Výstup by bol takýto:

spracovanie prvku JSON s uuid: fdbc75d0-5067-49df-9567-239f38f01b04 spracovanie prvku JSON s uuid: 81e6c856-ddaf-43d5-aec5-8ef977d3745e spracovanie prvku XML s uuid: 091bfcb8-2c68-493a-9308-203-ada

Ukazuje, že návštevník navštívil každý prvok našej štruktúry v závislosti od typu Element typu, odoslalo spracovanie do príslušnej metódy a mohlo načítať údaje z každého základného objektu.

6. Nevýhody

Ako každý návrhový vzor, ​​aj návštevník má svoje negatíva, najmä jeho použitie sťažuje údržbu kódu, ak potrebujeme do štruktúry objektu pridať nové prvky.

Napríklad, ak pridáme nové YamlElement, potom musíme aktualizovať všetkých existujúcich návštevníkov novou metódou požadovanou na spracovanie tohto prvku. Ak potom budeme mať ďalších desať alebo viac konkrétnych návštevníkov, bude ťažké aktualizovať ich všetkých.

Okrem toho sa pri použití tohto vzoru obchodná logika súvisiaca s jedným konkrétnym objektom rozšíri do všetkých implementácií návštevníkov.

7. Záver

Návštevnícky vzor je vynikajúci na oddelenie algoritmu od tried, v ktorých pracuje. Okrem toho uľahčuje pridávanie nových operácií iba poskytnutím novej implementácie návštevníka.

Ďalej nezávisíme od rozhraní komponentov, a ak sú odlišné, je to v poriadku, pretože máme samostatný algoritmus na spracovanie podľa konkrétneho prvku.

Okrem toho môže návštevník prípadne agregovať údaje na základe prvku, ktorým prechádza.

Ak chcete vidieť špecializovanejšiu verziu návrhového vzoru Visitor, pozrite si vzor návštevníka v Java NIO - použitie vzoru v JDK.

Kompletný kód je ako obvykle k dispozícii v projekte Github.


$config[zx-auto] not found$config[zx-overlay] not found