Prototype mønster i Java

1. Introduksjon

I denne opplæringen skal vi lære om en av de skapende designmønstrene - prototypemønsteret. Først vil vi forklare dette mønsteret og deretter fortsette å implementere det i Java.

Vi vil også diskutere noen av fordelene og ulempene.

2. Prototypemønster

Prototypemønsteret er generelt brukes når vi har en forekomst av klassen (prototype) og vi vil lage nye objekter ved å bare kopiere prototypen.

La oss bruke en analogi for å bedre forstå dette mønsteret.

I noen spill vil vi ha trær eller bygninger i bakgrunnen. Vi kan innse at vi ikke trenger å lage nye trær eller bygninger og gjengi dem på skjermen hver gang karakteren beveger seg.

Så vi oppretter en forekomst av treet først. Da kan vi lage så mange trær som vi vil fra denne forekomsten (prototype) og oppdatere deres posisjoner. Vi kan også velge å endre fargen på trærne for å få et nytt nivå i spillet.

Prototypemønsteret er ganske likt. I stedet for å lage nye objekter, vi må bare klone den prototypiske forekomsten.

3. UML-diagram

I diagrammet ser vi at klienten forteller prototypen å klone seg selv og lage et objekt. Prototype er et grensesnitt og erklærer en metode for å klone seg selv. Betong Prototype1 og BetongPrototype2 implementere operasjonen for å klone seg selv.

4. Gjennomføring

En av måtene vi kan implementere dette mønsteret på Java er å bruke klone () metode. For å gjøre dette, vil vi implementere Klonbar grensesnitt.

Når vi prøver å klone, vi bør velge mellom å lage en grunne eller en dyp kopi. Etter hvert koker det ned til kravene.

For eksempel, hvis klassen bare inneholder primitive og uforanderlige felt, kan vi bruke en grunne kopi.

Hvis den inneholder referanser til foranderlige felt, bør vi gå for en dyp kopi. Vi kan gjøre det med kopikonstruktører eller serialisering og deserialisering.

La oss ta eksemplet vi nevnte tidligere og fortsette å se hvordan du bruker prototypemønsteret uten å bruke Klonbar grensesnitt. For å gjøre dette, la oss lage en abstrakt klasse kalt Tre med en abstrakt metode 'kopiere'.

public abstract class Tree {// ... public abstract Tree copy (); }

La oss si at vi har to forskjellige implementeringer av Tre kalt PlasticTree og Furutre:

offentlig klasse PlasticTree utvider Tree {// ... @Override public Tree copy () {PlasticTree plasticTreeClone = new PlasticTree (this.getMass (), this.getHeight ()); plasticTreeClone.setPosition (this.getPosition ()); retur plastTreeClone; }}
offentlig klasse PineTree utvider treet {// ... @Override public Tree copy () {PineTree pineTreeClone = new PineTree (this.getMass (), this.getHeight ()); pineTreeClone.setPosition (this.getPosition ()); returner pineTreeClone; }}

Så her ser vi at klassene som strekker seg Tre og implementere kopiere metoden kan fungere som prototyper for å lage en kopi av seg selv.

Prototypemønster lar oss også lage kopier av objekter uten å avhenge av betongklassene. La oss si at vi har en liste over trær, og vi vil lage kopier av dem. På grunn av polymorfisme kan vi enkelt lage flere kopier uten å vite hvilke trær.

5. Testing

La oss nå teste det:

public class TreePrototypesUnitTest {@Test public void givenAPlasticTreePrototypeWhenClonedThenCreateA_Clone () {// ... PlasticTree plasticTree = new PlasticTree (masse, høyde); plasticTree.setPosition (posisjon); PlasticTree anotherPlasticTree = (PlasticTree) plasticTree.copy (); anotherPlasticTree.setPosition (otherPosition); assertEquals (posisjon, plasticTree.getPosition ()); assertEquals (otherPosition, anotherPlasticTree.getPosition ()); }}

Vi ser at treet har blitt klonet fra prototypen, og vi har to forskjellige forekomster av PlasticTree. Vi har nettopp oppdatert posisjonen i klonen og beholdt de andre verdiene.

La oss nå klone en liste over trær:

@Test public void givenA_ListOfTreesWhenClonedThenCreateListOfClones () {// create instances of PlasticTree and PineTree List trees = Arrays.asList (plasticTree, pineTree); Liste treeClones = trees.stream (). Kart (Tree :: copy) .collect (toList ()); // ... assertEquals (høyde, plasticTreeClone.getHeight ()); assertEquals (posisjon, plasticTreeClone.getPosition ()); }

Legg merke til at vi er i stand til å gjøre en dyp kopi av listen her uten å være avhengig av de konkrete implementeringene av Tre.

6. Fordeler og ulemper

Dette mønsteret er praktisk når det nye objektet vårt bare er litt forskjellig fra det eksisterende. I noen tilfeller kan forekomster bare ha noen få kombinasjoner av tilstand i en klasse. Så i stedet for å opprette nye forekomster, vi kan opprette forekomster med riktig tilstand på forhånd og deretter klone dem når vi vil.

Noen ganger kan vi støte på underklasser som bare avviker i sin tilstand. Vi kan eliminere disse underklassene ved å lage prototyper med den opprinnelige tilstanden og deretter klone dem.

Prototypemønster, som alle andre designmønstre, skal bare brukes når det er passende. Siden vi kloner gjenstandene, kan prosessen bli kompleks når det er mange klasser, og dermed føre til et rot. I tillegg er det vanskelig å klone klasser som har sirkulære referanser.

7. Konklusjon

I denne opplæringen lærte vi nøkkelbegrepene i prototypemønsteret og så hvordan vi implementerte det i Java. Vi diskuterte også noen av fordelene og ulempene.

Som vanlig er kildekoden for denne artikkelen tilgjengelig på Github.


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