Visitor Design Pattern i Java

1. Oversikt

I denne opplæringen vil vi introdusere et av GoFs atferdsmønstre - Visitor.

Først forklarer vi formålet og problemet det prøver å løse.

Deretter tar vi en titt på Visitors UML-diagram og implementering av det praktiske eksemplet.

2. Besøksdesignmønster

Hensikten med et besøksmønster er å definere en ny operasjon uten å innføre endringene i en eksisterende objektstruktur.

Tenk deg at vi har en sammensatteobjekt som består av komponenter. Objektets struktur er løst - vi kan enten ikke endre det, eller så planlegger vi ikke å legge til nye typer elementer i strukturen.

Nå, hvordan kan vi legge til ny funksjonalitet i koden vår uten endring av eksisterende klasser?

Besøksdesignmønsteret kan være et svar. For å si det enkelt, vi må gjøre er å legge til en funksjon som godtar besøkerklassen til hvert element i strukturen.

På den måten vil våre komponenter tillate besøkende implementering å "besøke" dem og utføre nødvendige handlinger på dette elementet.

Med andre ord vil vi trekke ut algoritmen som skal brukes på objektstrukturen fra klassene.

Følgelig vi vil gjøre god bruk av Åpen / Lukket-prinsippet da vi ikke vil endre koden, men vi vil fortsatt kunne utvide funksjonaliteten ved å tilby en ny Besøkende gjennomføring.

3. UML-diagram

På UML-diagrammet ovenfor har vi to implementeringshierarkier, spesialiserte besøkende og konkrete elementer.

Først og fremst bruker klienten en Visitor-implementering og bruker den på objektstrukturen. Den sammensatte gjenstanden itererer over komponentene og bruker den besøkende på hver av dem.

Spesielt relevant er det nå betongelementer (ConcreteElementA og BetongElementB) aksepterer a Besøkende, bare la det besøk dem.

Til slutt er denne metoden den samme for alle elementer i strukturen, den utfører dobbel forsendelse med å passere seg selv (via dette nøkkelord) til besøkendes besøksmetode.

4. Gjennomføring

Eksemplet vårt vil være skikk Dokument objekt som består av JSON og XML konkrete elementer; elementene har en felles abstrakt superklasse, Element.

De Dokument klasse:

public class Document utvider Element {List elements = new ArrayList (); // ... @Override public void accept (Visitor v) {for (Element e: this.elements) {e.accept (v); }}}

De Element klassen har en abstrakt metode som godtar Besøkende grensesnitt:

offentlig abstrakt ugyldig aksept (Visitor v);

Derfor, når du oppretter det nye elementet, navngi det JsonElement, må vi gi implementeringen av denne metoden.

Imidlertid, på grunn av besøksmønsterets natur, vil implementeringen være den samme, så i de fleste tilfeller vil det kreve at vi kopierer og limer inn kjeleplatekoden fra et annet, allerede eksisterende element:

offentlig klasse JsonElement utvider Element {// ... public void accept (Visitor v) {v.visit (this); }}

Siden elementene våre gjør det mulig å besøke dem av enhver besøkende, la oss si at vi vil behandle våre Dokument elementer, men hver av dem på en annen måte, avhengig av klassetype.

Derfor vil vår besøkende ha en egen metode for den gitte typen:

offentlig klasse ElementVisitor implementerer Visitor {@Override public void visit (XmlElement xe) {System.out.println ("behandler et XML-element med uuid:" + xe.uuid); } @ Overstyr offentlig tomt besøk (JsonElement je) {System.out.println ("behandler et JSON-element med uuid:" + je.uuid); }}

Her implementerer vår konkrete besøkende to metoder, tilsvarende en per hver type Element.

Dette gir oss tilgang til det bestemte objektet i strukturen som vi kan utføre nødvendige handlinger på.

5. Testing

For testformål, la oss ta en titt på VisitorDemoklasse:

public class VisitorDemo {public static void main (String [] args) {Visitor v = new ElementVisitor (); Dokument d = nytt dokument (genererUuid ()); d.elements.add (nye JsonElement (generereUuid ())); d.elements.add (ny JsonElement (generereUuid ())); d.elements.add (nytt XmlElement (generereUuid ())); d.accept (v); } // ...}

Først lager vi en ElementBesøkende, den inneholder algoritmen vi vil bruke på elementene våre.

Deretter setter vi opp vår Dokument med riktige komponenter og bruk den besøkende som vil bli akseptert av hvert element i en objektstruktur.

Utgangen vil være slik:

bearbeiding av et JSON-element med uuid: fdbc75d0-5067-49df-9567-239f38f01b04 prosessering av et JSON-element med uuid: 81e6c856-ddaf-43d5-aec5-8ef977d3745e bearbeiding av et XML-element med uuid: 091bfcb8-2c68-491a-931

Det viser at besøkende har besøkt hvert element i strukturen vår, avhengig av Element type sendte den behandlingen til riktig metode og kunne hente dataene fra hvert underliggende objekt.

6. Ulemper

Som hvert designmønster har til og med besøkende sine ulemper, spesielt bruken gjør det vanskeligere å opprettholde koden hvis vi trenger å legge til nye elementer i objektets struktur.

For eksempel hvis vi legger til nye YamlElement, da må vi oppdatere alle eksisterende besøkende med den nye metoden som er ønsket for behandling av dette elementet. Hvis vi har ti eller flere konkrete besøkende, kan det være vanskelig å oppdatere dem alle.

Når du bruker dette mønsteret, blir forretningslogikken knyttet til et bestemt objekt spredt over alle besøkendeimplementeringer.

7. Konklusjon

Besøksmønsteret er flott å skille algoritmen fra klassene den opererer på. I tillegg til det gjør det lettere å legge til ny operasjon, bare ved å tilby en ny implementering av Visitor.

Videre er vi ikke avhengige av komponentgrensesnitt, og hvis de er forskjellige, er det greit, siden vi har en egen algoritme for behandling per betongelement.

Videre kan besøkende til slutt samle data basert på elementet den krysser.

For å se en mer spesialversjon av Visitor-mønsteret, sjekk ut besøksmønsteret i Java NIO - bruken av mønsteret i JDK.

Som vanlig er den komplette koden tilgjengelig på Github-prosjektet.


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