原型模式
定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
实现的效果就是从一个对象再创建另一个可定制的对象,而且不需要知道任何创建的细节。一般在初始化的信息不发生变化的情况下,克隆是最好的办法。既隐藏了对象创建的细节,对性能也有大大的提高。不用重新初始化对象,而是动态的获得对象运行时的状态。
UML图
浅复制和深复制
浅复制:
创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该对象。
如果字段是值类型的,则对该字段执行逐位复制。
如果字段是引用类型,则复制引用不复制引用对象。源对象及副本引用同一对象
深复制:
创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该对象。
如果字段是值类型的,则对该字段执行逐位复制。
如果字段是引用类型,对象本身、对象所包含的所有成员变量都会被复制。源对象及副本引用不同对象
用例——简历复印(浅复制)
需要实现有一个简历功能,简历内容必须包括姓名,可以选择设置性别、年龄和工作经历。最终需要写出三份简历。
简历类
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private String timeArea;
private String company;
public Resume(String name){/
this.name = name;
}
//设置个人信息
public void setPersonalInfo(String sex, String age){
this.sex= sex;
this.age= age;
}
//设置工作经历
public void setWorkExperence(String timeArea, String Company){
this.timeArea= timeArea;
this.Company= Company;
}
//显示
public void display(){
System.out.println(name+","+sex+","+age);
System.out.println("工作经历"+timeArea+",工作公司"+Company);
}
/*浅克隆*/
@Override
public Object clone(){
return super.clone();//浅拷贝
}
}
客户端
static void Main(String[] Args){
Resume a = new Resume("大鸟");
a.setPersonalInfo("男","29");
a.setWorkExperence("1998-2000","XX公司");
Resume b = (Resume)a.clone();
b.setWorkExperence("1998-2006","YY公司");
Resume c = (Resume)a.clone();
c.setPersonalInfo("男","24");
c.setWorkExperence("1998-2003","ZZ公司");
a.display();
b.display();
c.display();
}
此时结果为
大鸟 男 29
工作经历:1998-2000 XX公司
大鸟 男 29
工作经历:1998-2006 YY公司
大鸟 男 24
工作经历:1998-2003 ZZ公司
但是,我们将工作时间和工作公司都放入工作经历类中。
工作经历类
class WorkExperence extends Cloneable{
private String workDate;
private String company;
public getWorkDate(){
return workDate;
}
public setWorkDate(){
this.workDate = setWorkDate;
}
public getCompany(){
return company;
}
public setCompany(){
this.company= company;
}
}
简历类
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExperence work;
//在构造时同时初始化工作经历
public Resume(String name){
this.name = name;
work = new WorkExperence();
}
//设置个人信息
public void setPersonalInfo(String sex, String age){
this.sex= sex;
this.age= age;
}
//设置工作经历
public void setWorkExperence(String workDate, String Company){
this.workDate= workDate;
this.Company= Company;
}
//显示
public void display(){
System.out.println(name+","+sex+","+age);
System.out.println("工作经历"+timeArea+",工作公司"+Company);
}
/*克隆*/
@Override
public Object clone(){
return super.clone();//浅拷贝
}
}
客户端
static void Main(String[] Args){
Resume a = new Resume("大鸟");
a.setPersonalInfo("男","29");
a.setWorkExperence("1998-2000","XX公司");
Resume b = (Resume)a.clone();
b.setWorkExperence("1998-2006","YY公司");
Resume c = (Resume)a.clone();
c.setPersonalInfo("男","24");
c.setWorkExperence("1998-2003","ZZ公司");
a.display();
b.display();
c.display();
}
此时结果为
大鸟 男 29
工作经历:1998-2003 ZZ公司
大鸟 男 29
工作经历:1998-2003 ZZ公司
大鸟 男 24
工作经历:1998-2003 ZZ公司
可以看出,此时如果被克隆的类(Resume)中还存在其他的类(WorkExperence)的话,克隆的对象对该类(WorkExperence)的引用都指向一个存储地址,实际上没有克隆。
用例——简历复印(深复制)
工作经历类
class WorkExperence extends Cloneable{
private String workDate;
private String company;
public getWorkDate(){
return workDate;
}
public setWorkDate(){
this.workDate = setWorkDate;
}
public getCompany(){
return company;
}
public setCompany(){
this.company= company;
}
public Object Clone(){
return super.clone();
}
}
简历类
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExperence work;
public Resume(String name){
this.name = name;
work = new WorkExperence();
}
//提供clone方法条用的私有构造函数,以便克隆“工作经历”的数据
public Resume(WorkExperence work){
this.work= (WorkExperence)work.clone();
}
//设置个人信息
public void setPersonalInfo(String sex, String age){
this.sex= sex;
this.age= age;
}
//设置工作经历
public void setWorkExperence(String workDate, String Company){
this.workDate= workDate;
this.Company= Company;
}
//显示
public void display(){
System.out.println(name+","+sex+","+age);
System.out.println("工作经历"+timeArea+",工作公司"+Company);
}
/*克隆*/
@Override
public Object clone(){
Resume obj = new Resume(this.work);
obj.name = this.name;
obj.sex= this.sex;
obj.age= this.age;
return obj;
}
}
客户端
static void Main(String[] Args){
Resume a = new Resume("大鸟");
a.setPersonalInfo("男","29");
a.setWorkExperence("1998-2000","XX公司");
Resume b = (Resume)a.clone();
b.setWorkExperence("1998-2006","YY公司");
Resume c = (Resume)a.clone();
c.setPersonalInfo("男","24");
c.setWorkExperence("1998-2003","ZZ公司");
a.display();
b.display();
c.display();
}
此时结果为
大鸟 男 29
工作经历:1998-2000 XX公司
大鸟 男 29
工作经历:1998-2006 YY公司
大鸟 男 24
工作经历:1998-2003 ZZ公司