原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
形 式:原型模式有两种模式:1. 浅复制(浅克隆)2. 深复制(深克隆)
1. 浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
2. 深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
深复制(深克隆):
怎么实现深复制(深克隆)呢?修改一下汽车类和汽车发动机类:
汽车类:
/* * 深克隆 */ public class Car implements Cloneable { public int type; // 引用的其他对象 public Engine engine; public Object clone() { Car temp = null; try { // 先把自己本身复制 temp = (Car) super.clone(); // 为了实现深度克隆,需要将对其他对象(在这里是engine)的引用都复制过去。 temp.engine = (Engine) engine.clone(); } catch (CloneNotSupportedException e) { // should never happen } return temp; } }
发动机类:
public class Engine implements Cloneable { public int model; /** * 为了实现深度克隆,需要给在Lay1中被应用的对象lay2)也提供一个自己克隆自身的方法 */ public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { } return clone; } }
客户端调用不变。
运行结果:
-----创建汽车1----- 汽车1款式:1 汽车1的发动机型号:1 ----汽车1--克隆-->汽车2---- 汽车2款式:2 汽车2的发动机型号:2 汽车1款式:1 汽车1的发动机型号:1
根据运行结果可以发现,深复制(深克隆)把要复制的对象所引用的对象都复制了一遍。
所以,当设定汽车2的发动机型号为2 时,汽车1的发动机型号还是1,没有变化。
因为,汽车1和汽车2拥有了两个不同的发动机。
利用串行化来做深复制(深克隆):
汽车类
实现了串行(序列)化接口,并使用了在流中读取和写入对象。
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /* * 汽车类 * * 序列化的方式实现深克隆(deep clone) */ public class Car implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = 1859639569305572020L; // 汽车款式 public int type; // 引用的其他对象,汽车发动机 public Engine engine; public Object clone() { try { // 将对象写到流里,把对象写到流里的过程是串行化(Serilization)过程 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo; oo = new ObjectOutputStream(bo); oo.writeObject(this); // 从流里读出来,把对象从流中读出来的并行化(Deserialization)过程 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi = new ObjectInputStream(bi); return (oi.readObject()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block return null; } catch (IOException e) { // TODO Auto-generated catch block return null; } } }
汽车发动机类:
import java.io.Serializable; public class Engine implements Cloneable, Serializable { /** * Car对象以及对象内部所有引用到的对象engine都是可串行化的 */ private static final long serialVersionUID = -6228724315977120960L; public int model; }
客户端调用不变。
运行结果:
根据运行结果可以发现,通过串行化的方式也实现了深复制(可克隆)。
所以,当设定汽车2的发动机型号为2 时,汽车1的发动机型号还是1,没有变化。
因为,汽车1和汽车2拥有了两个不同的发动机。