1. 定义
原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
2. 实现
2.1 Cloneable接口clone方法
2.1.1 Product
实现Cloneable接口clone方法,clone方法中编写深拷贝逻辑
class Product implements Cloneable {
private String part1;
private String part2;
private String part3;
private String part4;
private Info info;
public Product(String part1, String part2, String part3, String part4, Info info) {
this.part1 = part1;
this.part2 = part2;
this.part3 = part3;
this.part4 = part4;
this.info = info;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
public String getPart4() {
return part4;
}
public void setPart4(String part4) {
this.part4 = part4;
}
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
@Override
public String toString() {
return this.hashCode() + " Product{" +
"part1='" + part1 + '\'' +
", part2='" + part2 + '\'' +
", part3='" + part3 + '\'' +
", part4='" + part4 + '\'' +
", info=" + info +
'}';
}
@Override
protected Product clone() throws CloneNotSupportedException {
//深拷贝
Product clone = (Product) super.clone();
Info info = this.info.clone();
clone.setInfo(info);
return clone;
}
}
Info作为product的属性,同样实现Cloneable的clone方法,以便实现深拷贝
class Info implements Cloneable {
private String name;
public Info(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return this.hashCode() + " prototype.Info{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Info clone() throws CloneNotSupportedException {
return (Info) super.clone();
}
}
2.1.2 使用及测试
public static void main(String[] args) throws CloneNotSupportedException {
Info info1 = new Info("info1");
Product product = new Product("part1", "part2", "part3", "part4", info1);
//clone
Product clone = product.clone();
//打印对比
System.out.println("original: "+product);
System.out.println("clone: "+clone);
//打印结果:可以看到hashcode 不一样,说明已经实现了深拷贝
// original: 460141958 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=1163157884 prototype.Info{name='info1'}}
// clone: 1956725890 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=356573597 prototype.Info{name='info1'}}
//修改info打印对比
product.getInfo().setName("info2");
System.out.println("original: "+product);
System.out.println("clone: "+clone);
// 打印结果:修改原始product.info后,clone.info没有变化,说明实现了深拷贝
// original: 460141958 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=1163157884 prototype.Info{name='info2'}}
// clone: 1956725890 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=356573597 prototype.Info{name='info1'}}
}
2.2 序列化机制实现(不推荐)
修改clone实现逻辑
@Override
protected Product clone() throws CloneNotSupportedException {
//深拷贝
// Product clone = (Product) super.clone();
// Info info = this.info.clone();
// clone.setInfo(info);
// return clone;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (ObjectOutputStream oss = new ObjectOutputStream(byteArrayOutputStream)) {
oss.writeObject(this);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
try (ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream)) {
Product product = null;
product = (Product) ois.readObject();
return product;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
3. 应用场景
当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式 。