一、简单介绍
原型模式(Prototype)是用于创建重复的对象,同时又能保证性能。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
二、实现方法
1、浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
public class PrototypeExample {
public static void main(String[] args) throws CloneNotSupportedException {
Prototype prototype = new Prototype("Hello World");
Prototype cloneObject = (Prototype) prototype.clone();
System.out.println(prototype.hashCode() + prototype.toString());
System.out.println(cloneObject.hashCode() + cloneObject.toString());
// 浅拷贝?深拷贝?
System.out.println(prototype.getType().hashCode());
System.out.println(cloneObject.getType().hashCode());
}
}
class Prototype implements Cloneable {
private String name;
private Type type;
public Prototype(String name) {
this.name = name;
this.type = new Type(name);
}
// 省略getter、setter方法
@Override
protected Object clone() throws CloneNotSupportedException {
// 默认的克隆方法(浅拷贝)
return super.clone();
}
@Override
public String toString() {
return " " + name + " " + type.getTypeName();
}
}
class Type {
private String typeName;
// 省略getter、setter方法
}
结果:
这里我们会发现,浅拷贝后Prototype内部的Type类型的引用,依然是指向同一个实例(共享同一块内存)。
2、深拷贝
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
深拷贝一般有两种方法,代码与上面的相似,下面只放出clone()方法的重写:
(1)、层层clone的方法
在浅拷贝的基础上实现,给引用类型的属性添加克隆方法,并且在拷贝的时候也实现引用类型的拷贝。此种方法由于要在多个地方实现拷贝方法,可能会造成混论。
class Prototype implements Cloneable {
......
@Override
protected Object clone() throws CloneNotSupportedException {
Prototype cloneObject = (Prototype) super.clone();
cloneObject.type = (Type) cloneObject.type.clone();
return cloneObject;
}
}
class Type implements Cloneable{
......
@Override
protected Object clone() throws CloneNotSupportedException {
// 如果该类的成员变量也有引用类型,其同样需要重写该方法
return super.clone();
}
}
结果:
(2)、利用串行化来做深拷贝
为避免复杂对象中使用clone方法可能带来的换乱,可以使用串化来实现深拷贝。先将对象写到流里,然后再从流里读出来。
class Prototype implements Cloneable, Serializable{
......
@Override
protected Object clone() {
Prototype prototype = null;
ByteArrayOutputStream os = null;
ObjectOutputStream oos = null;
ByteArrayInputStream is = null;
ObjectInputStream ois = null;
try {
// 输出到流中
os = new ByteArrayOutputStream();
oos = new ObjectOutputStream(os);
oos.writeObject(this);
// 从流中读出
is = new ByteArrayInputStream(os.toByteArray());
ois = new ObjectInputStream(is);
prototype = (Prototype) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
try {
if (os != null) {
os.close();
}
if (oos != null) {
oos.close();
}
if (is != null) {
is.close();
}
if (ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return prototype;
}
}
class Type implements Serializable{
......
}
结果: