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; } }