在一些情景下面,会需要把一些重复的资料如 简历,模板等进行复制使用,所以要是手动就太麻烦了,所以在java代码设计中就有了原型模式,即克隆模式。
每个需要克隆的类都要有一个Clone方法,并且实现Cloneable接口,不然会报CloneNotSupportedException这个异常。
原型模式有两种状态:浅复制与深复制。
浅复制:调用的是原类型的内存地址,其实跟原先的类一样。
深复制:复制原先的数据,并且在内存中重新开辟一块内存空间,即一个新的对象。
例子如下:
package effective.yuanxing;
public class WorkExperience implements Cloneable {
private String workDate;
public String WorkDate;
private String company;
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(){
Object obj = null;
try {
obj = super.clone();
return obj;
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("不支持克隆");
return null ;
}
}
}
浅克隆:
package effective.yuanxing;
public class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExperience work;
public Resume(String name ){
this.name = name;
work = new WorkExperience();
}
//设置个人信息
public void SetPersonalInfo(String sex , String age){
this.sex = sex;
this.age = age;
}
//设置工作经历
public void SetWorkExperoence(String workDate , String company){
work.WorkDate = workDate;
work.Company = company;
}
//显示
public void Display(){
System.out.println("name:"+name +"sex:"+sex+"age: "+age);
System.out.println("工作经历:"+work.WorkDate+work.Company);
}
public Object Clone(){
try {
return (Object)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWorkExperoence("2015-2018", "XX公司");
Resume b =(Resume)a.Clone();
b.SetPersonalInfo("2016-2018", "yy企业");
Resume c =(Resume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkExperoence("1998-2003", "zo企业");
a.Display();
b.Display();
c.Display();
System.out.println(a.work==b.work);
System.out.println(a.work.Company);
}
}
结果:
name:大鸟sex:男age: 29
工作经历:1998-2003zo企业
name:大鸟sex:2016-2018age: yy企业
工作经历:1998-2003zo企业
name:大鸟sex:男age: 24
工作经历:1998-2003zo企业
true
zo企业
可见浅复制的 work对象为同一个对象。并且原来的Company也会被修改,即访问的是原来的对象。
深复制:
package effective.yuanxing;
public class DeepResume {
private String name;
private String sex;
private String age;
private WorkExperience work;
public DeepResume(String name ){
this.name = name;
work = new WorkExperience();
}
public DeepResume(WorkExperience work){
this.work = (WorkExperience)work.Clone();
}
//设置个人信息
public void SetPersonalInfo(String sex , String age){
this.sex = sex;
this.age = age;
}
//设置工作经历
public void SetWorkExperoence(String workDate , String company){
work.WorkDate = workDate;
work.Company = company;
}
//显示
public void Display(){
System.out.println("name:"+name +"sex:"+sex+"age: "+age);
}
public Object Clone(){
DeepResume obj = new DeepResume(this.work);
obj.name = this.name;
obj.sex = this.sex;
obj.age = this.age;
return obj;
}
public static void main(String[] args) {
DeepResume a = new DeepResume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWorkExperoence("2015-2018", "XX公司");
DeepResume b =(DeepResume)a.Clone();
b.SetPersonalInfo("2016-2018", "yy企业");
DeepResume c =(DeepResume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkExperoence("1998-2003", "zz企业");
a.Display();
b.Display();
c.Display();
System.out.println(b.work==c.work);
System.out.println(a.work.Company);
}
}
结果:
name:大鸟sex:男age: 29
name:大鸟sex:2016-2018age: yy企业
name:大鸟sex:男age: 24
false
XX公司
可见它们的work对象重新创建。
应用场景:类似一个像下围棋 五子棋时,创建棋子的时候就可以用原型模式创建旗子