原型模型(Prototype)
通过给出一个原型对象来指明所要创建的对象类型,然后用复制这个原型对象的办法创建出更多的同类型对象。
案例-简历问题
原代码
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 setPersonInfo(String sex,String age)
{
this.age=age;
this.sex=sex;
}
public void setWorkExperience(String timeArea,String company)
{
this.timeArea=timeArea;
this.company=company;
}
public void display()
{
System.out.println(name+" "+sex+" "+age);
System.out.println("工作经历:"+timeArea+" "+company);
}
}
public class main {
public static void main(String[] args) {
Resume a=new Resume("大鸟");
a.setPersonInfo("男", "29");
a.setWorkExperience("1998-2000", "XX公司");
Resume b=new Resume("大鸟");
b.setPersonInfo("男", "29");
b.setWorkExperience("1998-2000", "XX公司");
Resume c=new Resume("大鸟");
c.setPersonInfo("男", "29");
c.setWorkExperience("1998-2000", "XX公司");
a.display();
b.display();
c.display();
}
}
三份简历需要三次实例化。这样的客户端代码很麻烦,如果要20份。就需要改20次实例化。如果写错了个字,就要改20次。
(java原型模式有clone()方法只需用java.lang.Cloneable)
import java.util.*;
import java.lang.*;
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 setPersonInfo(String sex,String age)
{
this.age=age;
this.sex=sex;
}
public void setWorkExperience(String timeArea,String company)
{
this.timeArea=timeArea;
this.company=company;
}
public void display()
{
System.out.println(name+" "+sex+" "+age);
System.out.println("工作经历:"+timeArea+" "+company);
}
public Resume clone()
{
try
{
return(Resume)super.clone();
}catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return null;
}
}
public class main {
public static void main(String[] args) {
Resume a=new Resume("大鸟");
a.setPersonInfo("男", "29");
a.setWorkExperience("1998-2000", "XX公司");
Resume b=a.clone();
b.setWorkExperience("1998-2006", "XX企业");
Resume c=a.clone();
c.setPersonInfo("男", "24");
c.setWorkExperience("1998-2000", "XX公司");
a.display();
b.display();
c.display();
}
}
优点:
- 代码简洁。
- 性能很大提高。不用每次都初始化,而是动态获取对象运行时的状态。
但是clone()方法复制字段,如果字段是值类型则逐位复制;如果是引用类型,则复制引用(地址)但不复制引用的对象。
class WorkExperience
{
private String workdate;
private 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;
}
}
class Resume implements Cloneable
{
private String name;
private String age;
private String sex;
private WorkExperience work=new WorkExperience();
public Resume(String name)
{
this.name=name;
}
public void setPersonInfo(String sex,String age)
{
this.age=age;
this.sex=sex;
}
public void setWorkExperience(String workdate,String company)
{
work.setWorkdate(workdate);
work.setCompany(company);
}
public void display()
{
System.out.println(name+" "+sex+" "+age);
System.out.println("工作经历:"+work.getWorkdate()+" "+work.getCompany());
}
public Resume clone()
{
try
{
return(Resume)super.clone();
}catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return null;
}
}
public class main {
public static void main(String[] args) {
Resume a=new Resume("大鸟");
a.setPersonInfo("男", "29");
a.setWorkExperience("1998-2000", "XX公司");
Resume b=a.clone();
b.setWorkExperience("1998-2006", "YY企业");
Resume c=a.clone();
c.setWorkExperience("1998-2003", "ZZ公司");
a.display();
b.display();
c.display();//浅复制,只修改b和c的工作经历,三个经历都变成了最后设置的工作经历。工作经历类是引用类型。
}
}
结果为
大鸟 男 29
工作经历:1998-2003 ZZ公司
大鸟 男 29
工作经历:1998-2003 ZZ公司
大鸟 男 29
工作经历:1998-2003 ZZ公司
这里需要把复制的对象所引用的对象都复制一遍,这种称为"深复制"。深复制把引用的对象的变量指向复制过的新对象,而不是原有的引用对象。
深复制:
class WorkExperience implements Cloneable//抽象原型角色
{
private String workdate;
private 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 WorkExperience clone()
{
try
{
return(WorkExperience)super.clone();
> super.clone()浅复制
}catch(CloneNotSupportedException e)
{
e.printStackTrace();
}
return null;
}
}
class Resume implements Cloneable//抽象原型角色
{
private String name;
private String age;
private String sex;
private WorkExperience work=new WorkExperience();
public Resume(String name)
{
this.name=name;
}
public void setPersonInfo(String sex,String age)
{
this.age=age;
this.sex=sex;
}
public void setWorkExperience(String workdate,String company)
{
work.setWorkdate(workdate);
work.setCompany(company);
}
public void display()
{
System.out.println(name+" "+sex+" "+age);
System.out.println("工作经历:"+work.getWorkdate()+" "+work.getCompany());
}
public Resume clone()
{
Resume obj=new Resume(name);
obj.sex=this.sex;
obj.age=this.age;
obj.work=work.clone();//引用类型
return obj;
}
}
public class main {
public static void main(String[] args) {
Resume a=new Resume("大鸟");
a.setPersonInfo("男", "29");
a.setWorkExperience("1998-2000", "XX公司");
Resume b=a.clone();
b.setWorkExperience("1998-2006", "YY企业");
Resume c=a.clone();
c.setWorkExperience("1998-2003", "ZZ公司");
a.display();
b.display();
c.display();
}
}
克隆的实现方法:浅复制和深复制
浅复制只克隆按值传递的数据;
深复制除拷贝值之外还复制引用类型。