package com.DesignPatterns; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * The prototype is typically used to clone an object, i.e. to make a copy of an * object. When an object is complicated or time consuming to be created , you * may take prototype pattern to make such object cloneable. Assume the Complex * class is a complicated, you need to implement Cloneable interface and * override the clone method(protected Object clone()). */ public class ProtoType { public static final int SHALLOW_COPY = 0; public static final int CLONEABLE_COPY = 1; public static final int SERIALIZABLE_COPY = 2; public static void printDatainfo(int copyType, Complex complex) throws CloneNotSupportedException, IOException, ClassNotFoundException { complex.id = 123; complex.city = "New York"; complex.populations = new int[]{1, 2, 3, 4, 5}; if (copyType == SHALLOW_COPY || copyType == CLONEABLE_COPY) { complex.clonedQuoted = new ClonedQuoted(456, "London"); } if (copyType == SHALLOW_COPY || copyType == SERIALIZABLE_COPY) { complex.serializedQuoted = new SerializedQuoted(789, "Paris"); } Complex copyedComplex = null; if (copyType == SHALLOW_COPY) { complex.isShallowCopy = true; copyedComplex = (Complex) complex.clone(); } else if (copyType == CLONEABLE_COPY) { complex.isShallowCopy = false; copyedComplex = (Complex) complex.clone(); } else if (copyType == SERIALIZABLE_COPY) { copyedComplex = (Complex) deepCopy(complex); } System.out.println("change String or int value:"); complex.id = 321; complex.city = "纽约"; System.out.println(complex); System.out.println(copyedComplex); System.out.println(); System.out.println("change Array value:"); complex.populations[0] = 5; System.out.println(complex); System.out.println(copyedComplex); System.out.println(); if (copyType == SHALLOW_COPY || copyType == CLONEABLE_COPY) { System.out.println("change Cloneable Object value:"); complex.clonedQuoted.id = 654; complex.clonedQuoted.city = "伦敦"; System.out.println(complex); System.out.println(copyedComplex); System.out.println(); } if (copyType == SHALLOW_COPY || copyType == SERIALIZABLE_COPY) { System.out.println("change Serializable Object value:"); complex.serializedQuoted.id = 987; complex.serializedQuoted.city = "巴黎"; System.out.println(complex); System.out.println(copyedComplex); } } public static Object deepCopy(Object obj) throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException { /** * A shallow copy of the original object can only store the basic * variable just as int, boolean, etc. If the cloned object changed the * value of quoted object just as Array, list, etc, the original object * will be changed accordingly, vice versa. */ Complex complex = new Complex(); System.out.println("Shallow copy:"); printDatainfo(SHALLOW_COPY, complex); /** * To avoid such side effect, you may use a deep copy instead of a * shallow copy. There are 2 ways to implement it. */ complex = new Complex(); System.out.println(); System.out .println("**********************************************************************************"); System.out.println(); System.out.println("Deep copy(implement by cloneable):"); printDatainfo(CLONEABLE_COPY, complex); complex = new Complex(); System.out.println(); System.out .println("**********************************************************************************"); System.out.println(); System.out.println("Deep copy(implement by Serializable):"); printDatainfo(SERIALIZABLE_COPY, complex); } } class Complex implements Cloneable, Serializable { static final long serialVersionUID = 1L; int id; String city; int[] populations; ClonedQuoted clonedQuoted; SerializedQuoted serializedQuoted; boolean isShallowCopy; @Override protected Object clone() throws CloneNotSupportedException { Complex complex = (Complex) super.clone(); if (!isShallowCopy) { complex = (Complex) super.clone(); complex.clonedQuoted = ((ClonedQuoted) complex.clonedQuoted.clone()); complex.populations = complex.populations.clone(); } return complex; } @Override public String toString() { String str = "Complex:{ {id=" + id + ", city=" + city + ", populations="; for (int i : populations) { str += i + ","; } str = str.substring(0, str.length() - 1) + "}*****"; if (clonedQuoted != null) { str += "Cloned: {id=" + clonedQuoted.id + ", city=" + clonedQuoted.city + "}*****"; } if (serializedQuoted != null) { str += "Serialized: {id=" + serializedQuoted.id + ", city=" + serializedQuoted.city + "} }"; } return str; } } class ClonedQuoted implements Cloneable { int id; String city; public ClonedQuoted() { } public ClonedQuoted(int id, String city) { this.id = id; this.city = city; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class SerializedQuoted implements Serializable { static final long serialVersionUID = 2L; int id; String city; public SerializedQuoted() { } public SerializedQuoted(int id, String city) { this.id = id; this.city = city; } }