1.原型模式(Prototype)定义:指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
1.Cloneable接口/Object#clone方法详解
2.浅拷贝/深拷贝
3.序列化机制实现深拷贝
2.实现Cloneable接口,重写clone方法实现浅拷贝
class BaseInfo{
private String companyName;
public BaseInfo(String companyName){
this.companyName = companyName;
}
@Override
public String toString() {
return "["+ super.hashCode()+"],companyName:"+companyName;
}
}
class Product implements Cloneable{
private final String mainBoard; //1.先安装主板
private final String cpu; //2.再安装cpu
private final String memory; //3.再安装内存
private BaseInfo baseInfo;
public Product(String mainBoard,String cpu,String memory,BaseInfo baseInfo){
this.mainBoard = mainBoard;
this.cpu = cpu;
this.memory = memory;
this.baseInfo = baseInfo;
}
public Product build(){
/*
在这里实现组装操作
*/
return this;
}
@Override
protected Product clone() throws CloneNotSupportedException {
return (Product) super.clone();
}
@Override
public String toString() {
return "["+ super.hashCode()+"],mainBoard:"+mainBoard+",cpu:"+cpu+",memory:"+memory+",baseInfo:"+baseInfo;
}
}
public class BuilderTest {
public static void main(String[] args) {
BaseInfo baseInfo = new BaseInfo("appple");
Product product = new Product("jiJia","m1","32G",baseInfo).build();
Product product1 = null;
try {
product1 = product.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(product);
System.out.println(product1);
}
}
结果如上图,product和product1的两个类的hascode是不一样的,所以他们两个是不相同的类了,
但引用的其它子类baseInfo却是相同的,也就是product和product1的两个类共用一个引用了,这就是浅拷贝。
3.让引用子类也实现Cloneable接口,并重写clone方法实现深拷贝
class BaseInfo implements Cloneable{
private String companyName;
public BaseInfo(String companyName){
this.companyName = companyName;
}
@Override
protected BaseInfo clone() throws CloneNotSupportedException {
return (BaseInfo) super.clone();
}
@Override
public String toString() {
return "["+ super.hashCode()+"],companyName:"+companyName;
}
}
class Product implements Cloneable{
private final String mainBoard; //1.先安装主板
private final String cpu; //2.再安装cpu
private final String memory; //3.再安装内存
public BaseInfo baseInfo;
public Product(String mainBoard,String cpu,String memory,BaseInfo baseInfo){
this.mainBoard = mainBoard;
this.cpu = cpu;
this.memory = memory;
this.baseInfo = baseInfo;
}
public Product build(){
/*
在这里实现组装操作
*/
return this;
}
@Override
protected Product clone() throws CloneNotSupportedException {
Product clone = (Product) super.clone();
BaseInfo clone1 = this.baseInfo.clone();
clone.baseInfo = clone1;
return clone;
}
@Override
public String toString() {
return "["+ super.hashCode()+"],mainBoard:"+mainBoard+",cpu:"+cpu+",memory:"+memory+",baseInfo:"+baseInfo;
}
}
public class BuilderTest {
public static void main(String[] args) {
BaseInfo baseInfo = new BaseInfo("appple");
Product product = new Product("jiJia","m1","32G",baseInfo).build();
Product product1 = null;
try {
product1 = product.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(product);
System.out.println(product1);
}
}
4.利用java序列化机制实现深拷贝
cpu密集型,会比较消耗cpu的性能,效率没有上面3中的方法效率高。
class BaseInfo implements Serializable{
private static final long serialVersionUID = 42L;
private String companyName;
public BaseInfo(String companyName){
this.companyName = companyName;
}
@Override
public String toString() {
return "["+ super.hashCode()+"],companyName:"+companyName;
}
}
class Product implements Cloneable,Serializable{
private static final long serialVersionUID = 42L;
private final String mainBoard; //1.先安装主板
private final String cpu; //2.再安装cpu
private final String memory; //3.再安装内存
public BaseInfo baseInfo;
public Product(String mainBoard,String cpu,String memory,BaseInfo baseInfo){
this.mainBoard = mainBoard;
this.cpu = cpu;
this.memory = memory;
this.baseInfo = baseInfo;
}
public Product build(){
/*
在这里实现组装操作
*/
return this;
}
@Override
protected Product clone() throws CloneNotSupportedException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try(ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
objectOutputStream.writeObject(this);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
try(ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);) {
Product product = (Product) objectInputStream.readObject();
return product;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "["+ super.hashCode()+"],mainBoard:"+mainBoard+",cpu:"+cpu+",memory:"+memory+",baseInfo:"+baseInfo;
}
}
public class BuilderTest {
public static void main(String[] args) {
BaseInfo baseInfo = new BaseInfo("appple");
Product product = new Product("jiJia","m1","32G",baseInfo).build();
Product product1 = null;
try {
product1 = product.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(product);
System.out.println(product1);
}
}
应用场景:
当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式。
优点:
1.可以不耦合具体类的情况下克隆对象
2.避免重复的初始化代码
3.更方便的构建复杂对象
Spring源码中的应用
1org.springframework.beans.factory.support.AbstractBeanDefinition
2java.util.Arrays