Prototypový vzor v Jave

1. Úvod

V tomto výučbe sa dozvieme o jednom z vzorov stvorenia - prototypový vzor. Najprv vysvetlíme tento vzor a potom pokračujeme v jeho implementácii v Jave.

Rozoberieme tiež niektoré z jeho výhod a nevýhod.

2. Prototypový vzor

Prototypový vzor je všeobecne používa sa, keď máme inštanciu triedy (prototyp) a chceli by sme vytvoriť nové objekty iba skopírovaním prototypu.

Použime analógiu na lepšie pochopenie tohto vzorca.

V niektorých hrách chceme mať v pozadí stromy alebo budovy. Možno si uvedomíme, že nemusíme vytvárať nové stromy alebo budovy a vykresľovať ich na obrazovke zakaždým, keď sa postava pohne.

Najprv teda vytvoríme inštanciu stromu. Potom môžeme z tejto inštancie (prototypu) vytvoriť toľko stromov, koľko chceme, a aktualizovať ich polohy. Môžeme sa tiež rozhodnúť zmeniť farbu stromov na novú úroveň v hre.

Prototypový vzor je dosť podobný. Namiesto vytvárania nových objektov stačí naklonovať prototypovú inštanciu.

3. Diagram UML

Na diagrame vidíme, že klient hovorí prototypu, aby sa naklonoval a vytvoril objekt. Prototyp je rozhranie a deklaruje spôsob klonovania sám. Betónový prototyp1 a Betónový prototyp2 uskutočňujú operáciu na ich klonovanie.

4. Implementácia

Jedným zo spôsobov, ako môžeme implementovať tento vzor v Jave, je použitie klon () metóda. Aby sme to dosiahli, implementovali by sme Cloneable rozhranie.

Keď sa pokúšame klonovať, mali by sme sa rozhodnúť medzi vytvorením plytkej alebo hlbokej kópie. Nakoniec to spadne podľa požiadaviek.

Napríklad ak trieda obsahuje iba primitívne a nemenné polia, môžeme použiť plytkú kópiu.

Ak obsahuje odkazy na premenlivé polia, mali by sme vyhľadať hĺbkovú kópiu. Mohli by sme to urobiť s kopírovacie konštruktory alebo serializácia a deserializácia.

Zoberme si príklad, ktorý sme už spomínali, a ukážeme si, ako použiť prototypový vzor bez použitia znaku Cloneable rozhranie. Aby sme to dosiahli, vytvorme abstraktné trieda volala Strom s abstraktné metóda „Kopírovať“.

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

Teraz povedzme, že máme dve rôzne implementácie Strom zavolal PlasticTree a Borovica:

verejná trieda PlasticTree rozširuje Tree {// ... @Override public Tree copy () {PlasticTree plasticTreeClone = new PlasticTree (this.getMass (), this.getHeight ()); plasticTreeClone.setPosition (this.getPosition ()); vrátiť plasticTreeClone; }}
verejná trieda PineTree rozširuje strom {// ... @Override public Tree copy () {PineTree pineTreeClone = nový PineTree (this.getMass (), this.getHeight ()); pineTreeClone.setPosition (this.getPosition ()); spať pineTreeClone; }}

Takže tu vidíme, že triedy, ktoré sa rozširujú Strom a implementovať kópia metóda môže slúžiť ako prototypy na vytvorenie ich kópie.

Prototypový vzor nám tiež umožňuje vytvárať kópie objektov bez závislosti od konkrétnych tried. Povedzme, že máme zoznam stromov a chceli by sme z nich vytvoriť kópie. Kvôli polymorfizmu môžeme ľahko vytvoriť viac kópií bez toho, aby sme poznali typy stromov.

5. Testovanie

Teraz to otestujme:

verejná trieda TreePrototypesUnitTest {@Test public void givenAPlasticTreePrototypeWhenClonedThenCreateA_Clone () {// ... PlasticTree plasticTree = nový PlasticTree (hmotnosť, výška); plasticTree.setPosition (pozícia); PlasticTree anotherPlasticTree = (PlasticTree) plasticTree.copy (); anotherPlasticTree.setPosition (otherPosition); assertEquals (position, plasticTree.getPosition ()); assertEquals (otherPosition, anotherPlasticTree.getPosition ()); }}

Vidíme, že strom bol naklonovaný z prototypu a máme dva rôzne prípady PlasticTree. Práve sme aktualizovali pozíciu v klone a zachovali sme ďalšie hodnoty.

Teraz naklonujeme zoznam stromov:

@Test public void givenA_ListOfTreesWhenClonedThenCreateListOfClones () {// vytvoriť inštancie stromov zoznamov PlasticTree a PineTree = Arrays.asList (plasticTree, pineTree); Zoznam treeClones = trees.stream (). Map (Tree :: copy) .collect (toList ()); // ... assertEquals (height, plasticTreeClone.getHeight ()); assertEquals (position, plasticTreeClone.getPosition ()); }

Všimnite si, že tu môžeme urobiť hlbokú kópiu zoznamu bez toho, aby sme boli závislí od konkrétnych implementácií Strom.

6. Výhody a nevýhody

Tento vzor je užitočný, keď sa náš nový objekt líši len mierne od nášho existujúceho. V niektorých prípadoch môžu mať inštancie v triede iba niekoľko kombinácií stavov. Namiesto vytvárania nových inštancií teda inštancie môžeme vopred vytvoriť s príslušným stavom a potom ich kedykoľvek naklonovať.

Niekedy sa môžeme stretnúť s podtriedami, ktoré sa líšia iba svojim stavom. Tieto podtriedy môžeme vylúčiť vytvorením prototypov s počiatočným stavom a následným klonovaním.

Prototypový vzor, ​​rovnako ako každý iný dizajnový vzor, ​​by sa mal používať, iba ak je to vhodné. Pretože klonujeme objekty, proces by sa mohol komplikovať, keď existuje veľa tried, čo by malo za následok neporiadok. Okrem toho je ťažké klonovať triedy, ktoré majú cyklické odkazy.

7. Záver

V tomto tutoriáli sme sa naučili kľúčové koncepty prototypového vzoru a videli sme, ako ho implementovať v Jave. Diskutovali sme tiež o niektorých jeho kladoch a záporoch.

Ako obvykle je zdrojový kód tohto článku k dispozícii na stránkach Github.


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