I. Wzorce kreacyjne
1. Singleton
2. Budowniczy
3. Prototyp
4. Fabryka
5. Fabryka abstrakcyjna
II. Wzorce strukturalne
1. Adapter
2. Most
3. Kompozyt
4. Dekorator
5. Fasada
6. Pyłek
7. Pełnomocnik
III. Wzorce czynnościowe
1. Łańcuch zobowiązań
2. Polecenie
3. Interpreter
4. Iterator
5. Mediator
6. Pamiątka
7. Obserwator
8. Stan
9. Strategia
10. Metoda szablonowa
11. Odwiedzający

Prototyp - Prototype - wzorzec projektowy (design pattern) - java

1. Cel:
Uzyskać szybkie tworzenie obietku z domyślnymi wartościami,
aby nie było kosztowne użycie słowa kluczego new i przypisania wartości domyślnych.

2. Problem:
Mamy obiekt i chcemy stworzyć jego kopię wraz z domyślnymi wartościami,
więc musisz stworzyć nowy obiekt i przypisać mu wszystkie potrzebne pola.

3. Rozwiązanie:
Użycie interface-u Cloneable oraz metody clone do stworzenia kopii obiektu.
Prototyp odnosi się do obiektów implementującym wspólny interface

4. Diagram klas klasy prototyp:


5. Implementacja:
a) Implementacja wzorca Prototyp połączona z wzorcem projektowym singleton:
Abstrakcyjna klasa która będzie dziedziczona przez klasy właściwe.
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. public abstract class Element implements Cloneable {
  4.     private String tytul;
  5.     private double cena;
  6.     private String url;
  7.  
  8.     public Element() {
  9.     }
  10.  
  11.     public Element(String tytul,
  12.                    double cena,
  13.                    String url) {
  14.         this.tytul = tytul;
  15.         this.cena = cena;
  16.         this.url = url;
  17.     }
  18.  
  19.     public String getTytul() {
  20.         return tytul;
  21.     }
  22.  
  23.     public void setTytul(String tytul) {
  24.         this.tytul = tytul;
  25.     }
  26.  
  27.     public double getCena() {
  28.         return cena;
  29.     }
  30.  
  31.     public void setCena(double cena) {
  32.         this.cena = cena;
  33.     }
  34.  
  35.     public String getUrl() {
  36.         return url;
  37.     }
  38.  
  39.     public void setUrl(String url) {
  40.         this.url = url;
  41.     }
  42.  
  43.     public Element clone() {
  44.         try {
  45.             return (Element) super.clone();
  46.         } catch (CloneNotSupportedException e) {
  47.             e.printStackTrace();
  48.         }
  49.         return null;
  50.     }
  51. }
  52.  
Klasa Film która implementuje Element
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. public class Film extends Element {
  4.     int czasFilmu;
  5.  
  6.     public Film() {
  7.     }
  8.  
  9.     public Film(int czasFilmu,
  10.                 String tytul,
  11.                 double cena,
  12.                 String url) {
  13.         super(tytul, cena, url);
  14.         this.czasFilmu = czasFilmu;
  15.     }
  16.  
  17.     public int getCzasFilmu() {
  18.         return czasFilmu;
  19.     }
  20.  
  21.     public void setCzasFilmu(int czasFilmu) {
  22.         this.czasFilmu = czasFilmu;
  23.     }
  24. }
  25.  
Klasa Ksiazka która implementuje Element
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. public class Ksiazka extends Element {
  4.     int liczbaStron;
  5.  
  6.     public Ksiazka() {
  7.     }
  8.  
  9.     public Ksiazka(int liczbaStron,
  10.                    String tytul,
  11.                    double cena,
  12.                    String url) {
  13.         super(tytul, cena, url);
  14.         this.liczbaStron = liczbaStron;
  15.     }
  16.  
  17.     public int getLiczbaStron() {
  18.         return liczbaStron;
  19.     }
  20.  
  21.     public void setLiczbaStron(int liczbaStron) {
  22.         this.liczbaStron = liczbaStron;
  23.     }
  24.  
  25. }
  26.  
Obsługa metody clone dla wzorca prototypu
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5.  
  6. public class Rejestr {
  7.     private static Rejestr rejestr = new Rejestr();
  8.     private Map<String, Element> elementy = new HashMap<>();
  9.  
  10.     private Rejestr() {
  11.         zaladujElementy();
  12.     }
  13.  
  14.     public static Element stworzElement(String element) {
  15.         return rejestr.elementy.get(element).clone();
  16.     }
  17.  
  18.     private void zaladujElementy() {
  19.         Ksiazka ksiazka = new Ksiazka();
  20.         ksiazka.setLiczbaStron(200);
  21.         ksiazka.setCena(34.99);
  22.         ksiazka.setTytul("Banda czworga");
  23.         ksiazka.setUrl("java.edu.pl/book/3.prototype.php");
  24.         elementy.put("ksiazka", ksiazka);
  25.         Film film = new Film();
  26.         film.setCzasFilmu(130);
  27.         film.setTytul("Design patterns - prototype");
  28.         film.setCena(49.99);
  29.         film.setUrl("java.edu.pl/movies/3.prototype.php");
  30.         elementy.put("film", film);
  31.     }
  32. }
  33.  
Klasa prezentująca wzorzec:
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. public class PrototypeTest {
  4.     public static void main(String[] args) {
  5.  
  6.         Ksiazka ksiazka = (Ksiazka) Rejestr.stworzElement("ksiazka");
  7.         Film film = (Film) Rejestr.stworzElement("film");
  8.         System.out.println(ksiazka.getTytul() + " id:" + ksiazka.hashCode());
  9.         Ksiazka ksiazkaClone = (Ksiazka) Rejestr.stworzElement("ksiazka");
  10.         System.out.println(ksiazkaClone.getTytul() + " id:" + ksiazkaClone.hashCode());
  11.     }
  12. }
  13.  
Wynik:
Banda czworga id:1163157884
Banda czworga id:1956725890


b) implementując metodę clone można to zrobić na dwa sposoby:
- płytkie klonowanie
- głębkie klonowanie

Trzeba uważać czy na pewno chcemy płytkiego klonowania, może to stworzyć problemy:
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. public class Rekord {
  4. }
  5.  
  1. package pl.edu.java.designpatterns.prototype;
  2.  
  3. import java.util.List;
  4.  
  5. public class Statement implements Cloneable {
  6.     String query;
  7.     List<String> parametr;
  8.     Rekord rekord;
  9.     public Statement(String query, List<String> parametr, Rekord rekord) {
  10.         this.query = query;
  11.         this.parametr = parametr;
  12.         this.rekord = rekord;
  13.     }
  14.     public String getQuery() {
  15.         return query;
  16.     }
  17.     public List<String> getParametr() {
  18.         return parametr;
  19.     }
  20.     public Rekord getRekord() {
  21.         return rekord;
  22.     }
  23.  
  24.     public Object clone() {
  25.         try {
  26.             return super.clone();
  27.         } catch (CloneNotSupportedException e) {
  28.             e.printStackTrace();
  29.         }
  30.         return null;
  31.     }
  32. }
  33.  
I klasa testowa naszego przypadku.
  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. public class StatementTest {
  5.    public static void main(String[] args) {
  6.        List<String> list = new ArrayList<>();
  7.        list.add("NAME");
  8.        list.add("LASTNAME");
  9.        Statement stmt = new Statement("SELECT * FROM USERS", list, new Rekord());
  10.        System.out.println("stmt_Id:" + stmt.hashCode() +" ,listSize=" + stmt.parametr.size()
  11.             + " Rekord_Id: " + stmt.getRekord().hashCode());
  12.        Statement stmtClone = (Statement)stmt.clone();
  13.        stmtClone.getParametr().add("CITY");
  14.        System.out.println("stmtClone_Id:" + stmtClone.hashCode() +" ,listSize=" + stmtClone.parametr.size()
  15.             + " Rekord_Id: " + stmtClone.getRekord().hashCode());
  16.        System.out.println("stmt_Id:" + stmt.hashCode() +" ,listSize=" + stmt.parametr.size()
  17.             + " Rekord_Id: " + stmt.getRekord().hashCode());
  18.    }
  19. }
Wynik:
stmt_Id:1163157884 ,listSize=2 Rekord_Id: 1956725890
stmtClone_Id:356573597 ,listSize=3 Rekord_Id: 1956725890
stmt_Id:1163157884 ,listSize=3 Rekord_Id: 1956725890

Jest to płytkie kopiowanie przez co obiekty takie jak List<> i Rekord są tym samym obiektem po klonowaniu.
Zmiana elemtnów List<> powoduje że w obydwu obiektach stmt i stmtClone się zmieni
Gdy zrobimy operacje na obiekcie Rekord, również w dwóch miejscach będą widzoczne zmiany
Dlatego należało by stworzyć nową List<> listę obiektów oraz kolejny klon obiektu Rekord. Czyli głębokie klonowanie

6. Zastosowanie w kodzie java:
java.lang.Object#clone() - klasa musi implementować interface: java.lang.Cloneable
created by cv.java.org.pl © 2023 All Rights Reserved.