先看一段代码:
//简历类
public class Resume{
private String name;
private String age;
private String sex;
private String timeArea;
private String company;
public Resume (String name){
this.name = name;
}
//设置个人信息
public void setPersonalInfo(String age,String sex){
this.age= age;
this.sex= sex;
}
//设置工作经历
public void setWorkExperience(String timeArea ,String company){
this.timeArea = timeArea;
this.company = company;
}
//显示方法
public void Show(){
System.out.println(this.name+" "+this.age+" "+this.sex);
System.out.println(this.timeArea+" "+this.company);
}
}
public class StartMain {
public static void main(String[] args) throws Exception {
Resume a = new Resume("王小明");
a.setPersonalInfo("21", "男");
a.setWorkExperience("2018", "百度");
Resume b = a;
a.setPersonalInfo("22", "男");
b.setPersonalInfo("24", "女");
a.Show();
b.Show();
}
}
而打印出来的结果却是:
王小明 24 女
2018 百度
王小明 24 女
2018 百度
从结果可以看到,a和b对象中的值是完全一样的,可明明在代码中给a和b设置了不同的值,结果为什么一样?
Resume b = a这句代码其实是传的引用,而不是传值,所以不管a/b中哪个更改了值,都会修改另一个的值。
那么如何复制一份简历,并去修改自身的值呢?(这里忽略重新new的方式)
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建对象的细节。
代码修改后:
public class Resume implements Cloneable {
private String name;
private String age;
private String sex;
private String timeArea;
private String company;
public Resume (String name){
this.name = name;
}
//设置个人信息
public void setPersonalInfo(String age,String sex){
this.age= age;
this.sex= sex;
}
//设置工作经历
public void setWorkExperience(String timeArea ,String company){
this.timeArea = timeArea;
this.company = company;
}
public Object Clone() throws Exception {
return this.clone();
}
//显示方法
public void Show(){
System.out.println(this.name+" "+this.age+" "+this.sex);
System.out.println(this.timeArea+" "+this.company);
}
}
public class StartMain {
public static void main(String[] args) throws Exception {
Resume a = new Resume("王小明");
a.setPersonalInfo("21", "男");
a.setWorkExperience("2018", "百度");
Resume b = (Resume) a.Clone();
a.setPersonalInfo("22", "男");
b.setPersonalInfo("24", "女");
a.Show();
b.Show();
}
}
查看结果:
王小明 22 男
2018 百度
王小明 24 女
2018 百度
浅复制与深复制:
clone()方法:如果字段是值类型的,则对该字段进行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象,所以,原始对象和其复本引用同一个对象。
浅复制:被复制对象的所有变量都含有与原来的对象一样的值,而所有的对其他对象的引用都仍指向原来的对象。
深复制:把引用对象的变量指向复制过的新变量,而不是原有的被引用的对象。
上代码解释:
//工作经历类
public class WorkExperience {
public String workDate;
public String company;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
public class Resume implements Cloneable {
private String name;
private String age;
private String sex;
private WorkExperience work;
public Resume (String name){
this.name = name;
work = new WorkExperience();
}
//设置个人信息
public void setPersonalInfo(String age,String sex){
this.age= age;
this.sex= sex;
}
//设置工作经历
public void setWorkExperience(String workDate ,String company){
work.workDate = workDate;
work.company = company;
}
public Object Clone() throws Exception {
return this.clone();
}
//显示方法
public void Show(){
System.out.println(this.name+" "+this.age+" "+this.sex);
System.out.println(work.workDate+" "+work.company);
}
}
public class StartMain {
public static void main(String[] args) throws Exception {
Resume a = new Resume("王小明");
a.setPersonalInfo("21", "男");
a.setWorkExperience("2018", "百度");
Resume b = (Resume) a.Clone();
b.setPersonalInfo("24", "女");
b.setWorkExperience("2016", "阿里");
a.Show();
b.Show();
}
}
打印结果:
王小明 21 男
2016 阿里
王小明 24 女
2016 阿里
从结果可以看出,复制出的对象b和原对象a在设置值类型的变量时,各自修改各自的值,而对于引用类型(WorkExperience)的修改,不管a和b哪个修改了,都会修改另一个对象的值。
而我想要的是克隆后,新的对象无论怎么修改值,包括引用对象的值,都与之前的没有关系,该如何做到?
深复制的实现:
//工作经历类
public class WorkExperience implements Cloneable {
public String workDate;
public String company;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public Object Clone() throws Exception {
return this.clone();
}
}
public class Resume implements Cloneable {
private String name;
private String age;
private String sex;
private WorkExperience work;
public Resume (String name){
this.name = name;
work = new WorkExperience();
}
private Resume(WorkExperience work) throws Exception {
this.work = (WorkExperience) work.Clone();
}
//设置个人信息
public void setPersonalInfo(String age,String sex){
this.age= age;
this.sex= sex;
}
//设置工作经历
public void setWorkExperience(String workDate ,String company){
work.workDate = workDate;
work.company = company;
}
public Object Clone() throws Exception {
Resume resume = new Resume(this.work);
resume.name=this. name;
resume.age=this. age;
resume.sex=this. sex;
return resume;
}
//显示方法
public void Show(){
System.out.println(this.name+" "+this.age+" "+this.sex);
System.out.println(work.workDate+" "+work.company);
}
}
public class StartMain {
public static void main(String[] args) throws Exception {
Resume a = new Resume("王小明");
a.setPersonalInfo("21", "男");
a.setWorkExperience("2018", "百度");
Resume b = (Resume) a.Clone();
b.setPersonalInfo("24", "女");
b.setWorkExperience("2016", "阿里");
a.Show();
b.Show();
}
}
结果如下:
王小明 21 男
2018 百度
王小明 24 女
2016 阿里
这样就达到了深复制的效果,也就是原型模式的深复制。