Látogatói minta Java-ban

1. Áttekintés

Ebben az oktatóanyagban bemutatjuk az egyik viselkedési GoF tervezési mintát - a Látogatót.

Először elmagyarázzuk a célját és a problémát, amelyet megpróbál megoldani.

Ezután megnézzük a Látogató UML diagramját és a gyakorlati példa megvalósítását.

2. Látogató tervezési minta

A Látogató minta célja egy új művelet meghatározása anélkül, hogy egy meglévő objektumszerkezetet módosítanánk.

Képzelje el, hogy van egy összetettobjektum, amely összetevőkből áll. Az objektum szerkezete rögzített - vagy nem tudjuk megváltoztatni, vagy nem tervezünk új típusú elemeket hozzáadni a struktúrához.

Hogyan adhatunk új funkciót a kódunkhoz a meglévő osztályok módosítása nélkül?

A Látogató mintája válasz lehet. Egyszerűen fogalmazva, meg kell tennünk, hogy hozzáadunk egy függvényt, amely elfogadja a látogató osztályt a szerkezet minden eleméhez.

Így az összetevőink lehetővé teszik a látogató megvalósítás számára, hogy „meglátogassa” őket, és elvégezhesse az elemhez szükséges intézkedéseket.

Más szavakkal, kivonjuk az osztályokból az objektumszerkezetre alkalmazandó algoritmust.

Következésképpen, jól fogjuk használni a nyitott / zárt elvet mivel nem módosítjuk a kódot, de továbbra is képesek leszünk kibővíteni a funkcionalitást egy új szolgáltatással Látogató végrehajtás.

3. UML diagram

A fenti UML diagramon két megvalósítási hierarchiát, speciális látogatókat és konkrét elemeket használunk.

Először is, az ügyfél egy Visitor megvalósítást használ és alkalmazza az objektum szerkezetére. Az összetett objektum iterálja az összetevőket, és mindegyikre alkalmazza a látogatót.

Most különösen lényeges konkrét elemek (ConcreteElementA és ConcreteElementB) elfogadják a Látogató, egyszerűen megengedve látogatás őket.

Végül, ez a módszer a struktúra összes elemével megegyezik, kettős elosztást végez önmagának átadásával (a ez kulcsszó) a látogató látogatási módszeréhez.

4. Végrehajtás

Példánk egyedi lesz Dokumentum objektum, amely JSON és XML betonelemekből áll; az elemeknek van egy közös absztrakt szuperosztálya, az Elem.

A Dokumentum osztály:

public class A dokumentum kiterjeszti az Element {List elements = new ArrayList (); // ... @Orride public void accept (Visitor v) {for (Element e: this.elements) {e.accept (v); }}}

A Elem osztálynak van egy absztrakt módszere, amely elfogadja a Látogató felület:

public abstract void accept (Visitor v);

Ezért az új elem létrehozásakor nevezze el a JsonElement, ezt a módszert kell biztosítanunk a megvalósításhoz.

A Visitor minta jellegéből adódóan azonban a megvalósítás ugyanaz lesz, ezért a legtöbb esetben arra lenne szükség, hogy a kazánlap kódját más, már meglévő elemből másoljuk be:

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

Mivel elemeink lehetővé teszik, hogy bármely látogató meglátogassa őket, tegyük fel, hogy meg akarjuk dolgozni Dokumentum elemeket, de mindegyiket más módon, osztálytípusuktól függően.

Ezért látogatónknak külön módszere lesz az adott típushoz:

public class ElementVisitor megvalósítja a Visitor {@Override public void visit (XmlElement xe) {System.out.println ("XML elem feldolgozása uuiddal:" + xe.uuid); } @Orride public void visit (JsonElement je) {System.out.println ("JSON elem feldolgozása uuiddal:" + je.uuid); }}

Itt konkrét látogatónk két módszert alkalmaz, ennek megfelelően egy-egy módszert Elem.

Ez hozzáférést biztosít a szerkezet adott tárgyához, amelyen elvégezhetjük a szükséges műveleteket.

5. Tesztelés

Tesztelés céljából nézzük meg VisitorDemoosztály:

public class VisitorDemo {public static void main (String [] args) {Visitor v = new ElementVisitor (); D = új dokumentum (generatorUuid ()); d.elements.add (új JsonElement (generatorUuid ())); d.elements.add (új JsonElement (generatorUuid ())); d.elements.add (új XmlElement (generatorUuid ())); d. elfogadja (v); } // ...}

Először létrehozunk egy ElemLátogató, rendelkezik az algoritmussal, amelyet elemeinkre alkalmazunk.

Ezután beállítottuk Dokumentum megfelelő alkatrészekkel, és alkalmazza a látogatót, amelyet az objektumszerkezet minden eleme elfogad.

A kimenet a következő lenne:

JSON-elem feldolgozása uuid-del: fdbc75d0-5067-49df-9567-239f38f01b04 JSON-elem feldolgozása uuid: 81e6c856-ddaf-43d5-aec5-8ef977d3745e használatával

Ez azt mutatja, hogy a látogató meglátogatta struktúránk minden elemét, attól függően, hogy Elem típusú, a feldolgozást megfelelő módszerre küldte, és minden alapul szolgáló objektumból be tudta szerezni az adatokat.

6. Hátrányok

Mint minden tervezési minta, még a Látogatónak is megvannak a maga hátrányai, különös tekintettel a használatára megnehezíti a kód karbantartását, ha új elemeket kell hozzáadnunk az objektum struktúrájához.

Például ha újat adunk hozzá YamlElement, akkor az összes meglévő látogatót frissítenünk kell az elem feldolgozásához szükséges új módszerrel. Ezt követően, ha tíz vagy több konkrét látogatónk van, nehézkes lehet mindegyiket frissíteni.

Ettől eltekintve, ha ezt a mintát használja, akkor egy adott objektumhoz kapcsolódó üzleti logika az összes látogató megvalósításra kiterjed.

7. Következtetés

A Látogató minta kiválóan elválasztja az algoritmust azoktól az osztályoktól, amelyeken működik. Emellett könnyebbé teszi az új műveletek hozzáadását, csak a Látogató új megvalósításának biztosításával.

Továbbá nem függünk az összetevők interfészeitől, és ha eltérnek egymástól, akkor rendben van, mivel külön algoritmussal rendelkezünk a betonelemek feldolgozásához.

Sőt, a Látogató végül összesítheti az adatokat az általa bejárt elem alapján.

A Látogató tervezési minta speciálisabb verziójának megtekintéséhez tekintse meg a Java NIO látogatói mintáját - a minta használatát a JDK-ban.

Szokás szerint a teljes kód elérhető a Github projekten.