前言
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能,通俗来讲就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节,
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
1. 浅复制
创建Student对象实现Cloneable接口重写clone()方法
@ToString
public class Student implements Cloneable{
//姓名
private String name;
//性别
private String sex;
public void setStudentInfo(String name,String sex){
this.name = name;
this.sex = sex;
}
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
测试类:
@SpringBootTest
class PrototypeDemoApplicationTests {
@Test
void contextLoads() throws CloneNotSupportedException {
Student student = new Student();
student.setStudentInfo("张三","男");
Student cloneStudent = (Student)student.clone();
cloneStudent.setStudentInfo("李四","男");
System.out.println(student.toString());
System.out.println(cloneStudent.toString());
}
}
运行结果:
目前Student对象中都是String类型,而string是一种拥有值类型特点的特殊引用类型,重写了clone()后,当字段是值类型的,则会对该字段执行逐位复制,如果是引用类型则不会被克隆过来。
以示例说话
新增一个Address对象
@Data
public class Address {
//省份
private String province;
//市
private String city;
//区
private String area;
//街道
private String street;
}
Student对象改造
@ToString
public class Student implements Cloneable{
//姓名
private String name;
//性别
private String sex;
//地址
private Address address = new Address();
public void setStudentInfo(String name,String sex){
this.name = name;
this.sex = sex;
}
public void setAddressInfo(String province, String city, String area, String street){
address.setProvince(province);
address.setCity(city);
address.setArea(area);
address.setStreet(street);
}
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
测试类:
@SpringBootTest
class PrototypeDemoApplicationTests {
@Test
void contextLoads1() throws CloneNotSupportedException {
Student student = new Student();
student.setStudentInfo("张三","男");
student.setAddressInfo("浙江省","杭州市","西湖区","xx街道");
Student cloneStudent = (Student)student.clone();
cloneStudent.setStudentInfo("李四","男");
student.setAddressInfo("湖南省","长沙市","岳麓区","xx街道");
System.out.println(student.toString());
System.out.println(cloneStudent.toString());
}
}
运行结果:
Object类提供的clone()方法只是拷贝本对象,对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝。这种方式非常不安全,任何一个拷贝对象改变了私有变量的值,其他所有对象的变量的值都会随着改变。
2. 深复制
由于浅复制是有风险的 针对如上做出改动
Address对象改造 也实现Cloneable接口
@Data
public class Address implements Cloneable{
//省份
private String province;
//市
private String city;
//区
private String area;
//街道
private String street;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Student对象改造
@ToString
public class Student implements Cloneable{
//姓名
private String name;
//性别
private String sex;
//地址
private Address address = new Address();
public void setStudentInfo(String name,String sex){
this.name = name;
this.sex = sex;
}
public void setAddressInfo(String province, String city, String area, String street){
address.setProvince(province);
address.setCity(city);
address.setArea(area);
address.setStreet(street);
}
@Override
public Object clone() throws CloneNotSupportedException{
Student student = (Student) super.clone();
student.address = (Address) this.address.clone();
return student;
}
}
改造后运行结果
这样就实现了完全的拷贝,两个对象之间没有任何瓜葛,你改你的,我改我的,互不影响,这种拷贝就叫做深复制。
源码: https://download.csdn.net/download/javanbme/17853753