Wzorzec projektowy Prototype

Zadanie programistyczne 1

Smoki tworzą armię klonów. Trzeba wykonać klasę prototypową i umożliwić
tworzenie klonów przez klonowanie obiektów danej klasy oraz łatwe zmienianie
właściwości klonów w locie (jeśli trzeba). Zakłada się że wystarczy
klonowanie proste, gdyż smoki nie mają referencji do żadnych obiektów
złożonych.

Rozwiązanie 1

Klasa Klon
package prototype.simpleclone;
abstract class Klon implements Cloneable {
    String nazwa;
    String uzbrojenie;
    String dywizja;
    Klon() {
        nazwa = null;
        uzbrojenie = null;
        dywizja = null;
    }
    public abstract String getNazwa();
    public abstract void setNazwa(String nazwa);
    public abstract String getUzbrojenie();
    public abstract void setUzbrojenie(String uzbrojenie);
    public abstract String getDywizja();
    public abstract void setDywizja(String dywizja);
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return nazwa + " " + uzbrojenie + " " + dywizja;
    }
}
Klasa Smoklon
package prototype.simpleclone;
public class Smoklon extends Klon {
    public Smoklon() {
        super();
    }
    @Override
    public String getNazwa() {
        return nazwa;
    }
    @Override
    public void setNazwa(String nazwa) {
        this.nazwa = nazwa;
    }
    @Override
    public String getUzbrojenie() {
        return uzbrojenie;
    }
    @Override
    public void setUzbrojenie(String uzbrojenie) {
        this.uzbrojenie = uzbrojenie;
    }
    @Override
    public String getDywizja() {
        return dywizja;
    }
    @Override
    public void setDywizja(String dywizja) {
        this.dywizja = dywizja;
    }
}
Klasa Main
package prototype.simpleclone;
import java.util.Objects;
class Main {
    public static void main(String[] args) {
        Smoklon szablon = new Smoklon();
        System.out.println(szablon);
        szablon.setNazwa("klon1");
        szablon.setUzbrojenie("karabin maszynowy");
        szablon.setDywizja("pancerna");
        System.out.println(szablon);
        Smoklon klon2 = null;
        try {
            klon2 = (Smoklon) szablon.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(klon2);
        Objects.requireNonNull(klon2).setNazwa("klon2");
        System.out.println(klon2);
    }
}
Wynik
null null null
klon1 karabin maszynowy pancerna
klon1 karabin maszynowy pancerna
klon2 karabin maszynowy pancerna

Zadanie programistyczne 2

Smoki tworzą armię klonów, ale klony posiadają referencje do obiektu złożonego.
Gdyby sklonować obiekt przy użyciu klonowania prostego to wszystkie
obiekty miały by skopiowaną referencję do tego samego obiektu.
Gdyby klonowanym obiektem był ‘mozg smoka’ to wszystkie smoki miały by
jeden mózg.
Czasami każdy obiekt ma inną cechę np. datę powstania, wtedy trzeba użyć
klonowania złożonego, który wykona kopię obiektu głównego, a następnie kopię
obiektu wchodzącego w skład tego pierwszego.

Klasa Klon
package prototype.deepclone;
import java.util.*;
abstract class Klon implements Cloneable {
    String nazwa;
    String uzbrojenie;
    String dywizja;
    Date data;
    Klon() {
        nazwa = null;
        uzbrojenie = null;
        dywizja = null;
        data = null;
    }
    public abstract String getNazwa();
    public abstract void setNazwa(String nazwa);
    public abstract String getUzbrojenie();
    public abstract void setUzbrojenie(String uzbrojenie);
    public abstract String getDywizja();
    public abstract void setDywizja(String dywizja);
    public abstract Date getData();
    protected abstract void setData(Date data);
    @Override
    public Object clone() throws CloneNotSupportedException {
        Klon klon = (Klon) super.clone();
        klon.setData((Date) data.clone());
        return klon;
    }
    @Override
    public String toString() {
        return nazwa + " " + uzbrojenie + " " + dywizja + " " + data;
    }
}
Klasa Smoklon
package prototype.deepclone;
import java.util.*;
public class Smoklon extends Klon {
    public Smoklon() {
        super();
    }
    @Override
    public String getNazwa() {
        return nazwa;
    }
    @Override
    public void setNazwa(String nazwa) {
        this.nazwa = nazwa;
    }
    @Override
    public String getUzbrojenie() {
        return uzbrojenie;
    }
    @Override
    public void setUzbrojenie(String uzbrojenie) {
        this.uzbrojenie = uzbrojenie;
    }
    @Override
    public String getDywizja() {
        return dywizja;
    }
    @Override
    public void setDywizja(String dywizja) {
        this.dywizja = dywizja;
    }
    @Override
    public Date getData() {
        return data;
    }
    @Override
    public void setData(Date data) {
        this.data = data;
    }
}
Klasa Main
package prototype.deepclone;
import java.util.*;
class Main {
    public static void main(String[] args) {
        Smoklon szablon = new Smoklon();
        System.out.println(szablon);
        szablon.setNazwa("klon1");
        szablon.setUzbrojenie("karabin maszynowy");
        szablon.setDywizja("pancerna");
        szablon.setData(new Date());
        System.out.println(szablon);
        Smoklon klon2 = null;
        try {
            klon2 = (Smoklon) szablon.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(klon2);
        Objects.requireNonNull(klon2).setNazwa("klon2");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        klon2.setData(new Date());
        System.out.println("szablon: " + szablon);
        System.out.println("klon2: " + klon2);
    }
}
Wynik
null null null null
klon1 karabin maszynowy pancerna Thu Oct 25 09:27:53 CEST 2018
klon1 karabin maszynowy pancerna Thu Oct 25 09:27:53 CEST 2018
szablon: klon1 karabin maszynowy pancerna Thu Oct 25 09:27:53 CEST 2018
klon2: klon2 karabin maszynowy pancerna Thu Oct 25 09:27:55 CEST 2018

Zadanie programistyczne 3

Powstaje problem jak porównywać bądź sortować powstałe klony. Nie można
użyć interfejsu Comparable.
W zasadzie chyba jedyną możliwością, jest użycie interfejsu Comparator.

Rozwiązanie

Klasa Klon
package prototype.comp;
import java.io.*;
import java.util.*;
abstract class Klon implements Cloneable, Serializable {
    private static final long serialVersionUID = 1026112613759247281L;
    String nazwa;
    String uzbrojenie;
    String dywizja;
    Date data;
    Klon() {
        nazwa = null;
        uzbrojenie = null;
        dywizja = null;
        data = null;
    }
    public abstract String getNazwa();
    public abstract void setNazwa(String nazwa);
    public abstract String getUzbrojenie();
    public abstract void setUzbrojenie(String uzbrojenie);
    public abstract String getDywizja();
    public abstract void setDywizja(String dywizja);
    public abstract Date getData();
    protected abstract void setData(Date data);
    @Override
    public Object clone() throws CloneNotSupportedException {
        Klon klon = (Klon) super.clone();
        klon.setData((Date) data.clone());
        return klon;
    }
    @Override
    public String toString() {
        return nazwa + " " + uzbrojenie + " " + dywizja + " " + data;
    }
}
Klasa Smoklon
package prototype.comp;
import java.util.*;
public class Smoklon extends Klon {
    private static final long serialVersionUID = -288869537900173993L;
    public Smoklon() {
        super();
    }
    @Override
    public String getNazwa() {
        return nazwa;
    }
    @Override
    public void setNazwa(String nazwa) {
        this.nazwa = nazwa;
    }
    @Override
    public String getUzbrojenie() {
        return uzbrojenie;
    }
    @Override
    public void setUzbrojenie(String uzbrojenie) {
        this.uzbrojenie = uzbrojenie;
    }
    @Override
    public String getDywizja() {
        return dywizja;
    }
    @Override
    public void setDywizja(String dywizja) {
        this.dywizja = dywizja;
    }
    @Override
    public Date getData() {
        return data;
    }
    @Override
    public void setData(Date data) {
        this.data = data;
    }
}
Klasa DywizjaComparator
package prototype.comp;
import java.util.*;
class DywizjaComparator implements Comparator<Smoklon> {
    @Override
    public int compare(Smoklon o1, Smoklon o2) {
        return (o1.getDywizja()).compareTo(o2.getDywizja());
    }
}
Klasa Main
package prototype.comp;
import java.util.*;
class Main {
    public static void main(String[] args) {
        String[] tabl = {"pancerna", "piesza", "motocyklowa", "lotnicza"};
        ArrayList<Smoklon> list = new ArrayList<>();
        Smoklon szablon = new Smoklon();
        szablon.setNazwa("klon0");
        szablon.setUzbrojenie("karabin maszynowy");
        szablon.setData(new Date());
        szablon.setDywizja("pancerna");
        for (int i = 0; i < 20; i++) {
            Smoklon klon = null;
            try {
                klon = (Smoklon) szablon.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            Objects.requireNonNull(klon).setDywizja(tabl[randomInRange(0, tabl.length - 1)]);
            klon.setNazwa("klon" + i);
            klon.setData(new Date());
            list.add(klon);
        }
        //Te sama kolekcje mozna sortowac przy uzyciu roznych
        //komparatorow
        list.sort(new DywizjaComparator());
        for (Smoklon aList : list) {
            System.out.println(aList);
        }
    }
    private static int randomInRange(int min, int max) {
        int random = -1;
        if (min > max) {
            System.out.println("pierwsza liczba musi byc mniejsza od drugiej");
        } else {
            random = (int) (Math.floor(Math.random() * (max - min + 1)) + min);
        }
        return random;
    }
}
Wynik
klon10 karabin maszynowy lotnicza Thu Oct 25 09:44:19 CEST 2018
klon16 karabin maszynowy lotnicza Thu Oct 25 09:44:19 CEST 2018
klon2 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon4 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon7 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon13 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon15 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon18 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon19 karabin maszynowy motocyklowa Thu Oct 25 09:44:19 CEST 2018
klon0 karabin maszynowy pancerna Thu Oct 25 09:44:19 CEST 2018
klon3 karabin maszynowy pancerna Thu Oct 25 09:44:19 CEST 2018
klon5 karabin maszynowy pancerna Thu Oct 25 09:44:19 CEST 2018
klon17 karabin maszynowy pancerna Thu Oct 25 09:44:19 CEST 2018
klon1 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018
klon6 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018
klon8 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018
klon9 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018
klon11 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018
klon12 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018
klon14 karabin maszynowy piesza Thu Oct 25 09:44:19 CEST 2018

Klonowanie przez serializację

Klonowanie można wykonać przez serializację. W pakiecie ‘serial’
do klasy Klon dodano metody serializujące do pliku i z pliku oraz metodę
klonowania głębokiego klonuj() klonującą przy użyciu serializacji.
Warunkiem serializacji jest to że wszystkie klonowane obiekty implementują
interface Serializable lub są pochodnymi klas, które ten interfejs
implementują. Metod clone() i klonuj() można używać zamiennie.

Klasa Klon
package prototype.serial;
import java.io.*;
import java.util.*;
abstract class Klon implements Cloneable, Serializable {
    private static final long serialVersionUID = 1026112613759247281L;
    String nazwa;
    String uzbrojenie;
    String dywizja;
    Date data;
    Klon() {
        nazwa = null;
        uzbrojenie = null;
        dywizja = null;
        data = null;
    }
    public abstract String getNazwa();
    public abstract void setNazwa(String nazwa);
    public abstract String getUzbrojenie();
    public abstract void setUzbrojenie(String uzbrojenie);
    public abstract String getDywizja();
    public abstract void setDywizja(String dywizja);
    public abstract Date getData();
    protected abstract void setData(Date data);
    @Override
    public Object clone() throws CloneNotSupportedException {
        Klon klon = (Klon) super.clone();
        klon.setData((Date) data.clone());
        return klon;
    }
    @Override
    public String toString() {
        return nazwa + " " + uzbrojenie + " " + dywizja + " " + data;
    }
    // serializacja i zapis do pliku. Serializowany objekt musi
    // implementowac interface Serializable
    public static void serialize(Object obj, String outputFile) {
        try {
            FileOutputStream fos = new FileOutputStream(outputFile);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(obj);
            oos.flush();
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // odczytanie z pliku i deserializacja
    public static Object deserialize(String inputFile) {
        Object obj = new Object();
        try {
            FileInputStream fis = new FileInputStream(inputFile);
            ObjectInputStream ois = new ObjectInputStream(fis);
            try {
                obj = ois.readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return obj;
    }
    // glebokie klonowanie obiektu
    public static Object klonuj(Object object) {
        Object obj = new Object();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        try {
            ObjectInputStream ois = new ObjectInputStream(bais);
            try {
                obj = ois.readObject();
                ois.close();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return obj;
    }
}
Klasa Smoklon
package prototype.serial;
import java.util.*;
public class Smoklon extends Klon {
    private static final long serialVersionUID = -288869537900173993L;
    public Smoklon() {
        super();
    }
    @Override
    public String getNazwa() {
        return nazwa;
    }
    @Override
    public void setNazwa(String nazwa) {
        this.nazwa = nazwa;
    }
    @Override
    public String getUzbrojenie() {
        return uzbrojenie;
    }
    @Override
    public void setUzbrojenie(String uzbrojenie) {
        this.uzbrojenie = uzbrojenie;
    }
    @Override
    public String getDywizja() {
        return dywizja;
    }
    @Override
    public void setDywizja(String dywizja) {
        this.dywizja = dywizja;
    }
    @Override
    public Date getData() {
        return data;
    }
    @Override
    public void setData(Date data) {
        this.data = data;
    }
}

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *