原型模式prototype pattern,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式的结构图:
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。它采取复制原型对象的方法来创建对象的实例。
原型模式的代码:
abstract class Prototype{
private String id;
public Prototype(String id){
this.id =id;
}
public String id
{
get {return id;}
}
public abstract Prototype Clone(); //抽象类关键就是这样一个Clone方法
}
具体的原型类:
class ConcretePrototype :Prototype{
public ConcretePrototype (String id) :base(id){
}
public override Prototype Clone(){
return super.Clone();
}
}
客户端的代码:
static void main(String[] args){
ConcretePrototype cp1 = new ConcretePrototype("1");
ConcretePrototype cp2 = (ConcretePrototype)cp1.Clone();
}
Java语言是直接支持原型模式的,java.lang.Object是一切接口和类的父类,Object中提供了一个clone()方法来支持原型模式。如果一个对象想具有被复制的能力,必须实现Cloneable接口。复制份浅复制和深复制,浅复制是对基本数据类型和String类型而言,深复制是对其他引用类型而言,对于深复制,每个引用都要实现Cloneable接口。
下面以这样一个需求为例,面试都要做简历,现在要求有一个简历类,必须有姓名,可以设置性别,年龄,工作经历,最终需要两份这样的简历。
首先是一个浅复制的例子,这里有一个设置工作经历的方法:
package prototype.pattern;
public class ResumeShallow implements Cloneable {
private String mName=null;
private String mSex=null;
private String mAge=null;
private String mWork_time =null;
private String mWork_compony=null;
public ResumeShallow(String name){
this.mName = name;
}
public void setPersonalInfo(String sex,String age){
this.mSex = sex;
this.mAge = age;
}
public void setWorkExperience(String work_time,String compony){
this.mWork_time = work_time;
this.mWork_compony = compony;
}
public void display(){
System.out.println("Name :"+mName+",Sex:"+mSex+",Age:"+mAge);
System.out.println("Work experience,work-time:"+mWork_time+",work-compony:"+mWork_compony);
}
@Override
protected ResumeShallow clone() throws CloneNotSupportedException {
return (ResumeShallow)super.clone();
}
//客户端代码
public static void main(String[] args) throws CloneNotSupportedException{
ResumeShallow rA = new ResumeShallow("大牛");
rA.setPersonalInfo("男", "26");
rA.setWorkExperience("2015-2016", "QQ 企业");
ResumeShallow rB = (ResumeShallow)rA.clone();
rB.setPersonalInfo("女", "25");
rB.setWorkExperience("2012-2014", "WW 企业");
rA.display();
rB.display();
}
}
输出结果:
Name :大牛,Sex:男,Age:26
Work experience,work-time:2015-2016,work-compony:QQ 企业
Name :大牛,Sex:女,Age:25
Work experience,work-time:2012-2014,work-compony:WW 企业
然后是深复制的代码,现实中应该通常会再有一个工作经历的类:
先定义一个Workexperience 类,
package prototype.pattern;
public class WorkExperience implements Cloneable{
private String mWork_time =null;
private String mWork_compony=null;
public String getmWork_time() {
return mWork_time;
}
public void setmWork_time(String mWork_time) {
this.mWork_time = mWork_time;
}
public String getmWork_compony() {
return mWork_compony;
}
public void setmWork_compony(String mWork_compony) {
this.mWork_compony = mWork_compony;
}
@Override
protected WorkExperience clone() throws CloneNotSupportedException {
return (WorkExperience)super.clone();
}
}
public class ResumeDeep implements Cloneable {
private String mName=null;
private String mSex=null;
private String mAge=null;
private WorkExperience mWorkExperience =null;
public ResumeDeep(String name){
this.mName = name;
mWorkExperience = new WorkExperience();
}
public ResumeDeep(WorkExperience workexperience) throws CloneNotSupportedException{
//让工作经历完成clone,复制工作经历的数据
mWorkExperience = (WorkExperience)workexperience.clone();
}
public void setPersonalInfo(String sex,String age){
this.mSex = sex;
this.mAge = age;
}
public void setWorkExperience(String work_time,String compony){
mWorkExperience.setmWork_time(work_time);
mWorkExperience.setmWork_compony(compony);
}
public void display(){
System.out.println("Name :"+mName+",Sex:"+mSex+",Age:"+mAge);
System.out.println("Work experience,work-time:"+mWorkExperience.getmWork_time()
+",work-compony:"+mWorkExperience.getmWork_compony());
}
@Override
protected ResumeDeep clone() throws CloneNotSupportedException {
ResumeDeep mResumeDeep = new ResumeDeep(mWorkExperience);
mResumeDeep.mName = this.mName;
mResumeDeep.mSex = this.mSex;
mResumeDeep.mAge = this.mAge;
return mResumeDeep;
}
public static void main(String[] args) throws CloneNotSupportedException{
ResumeDeep rA = new ResumeDeep("大牛");
rA.setPersonalInfo("男", "26");
rA.setWorkExperience("2015-2016", "QQ 企业");
ResumeDeep rB = (ResumeDeep)rA.clone();
rB.setPersonalInfo("女", "25");
rB.setWorkExperience("2012-2014", "WW 企业");
rA.display();
rB.display();
}
}
输出结果:
Name :大牛,Sex:男,Age:26
Work experience,work-time:2015-2016,work-compony:QQ 企业
Name :大牛,Sex:女,Age:25
Work experience,work-time:2012-2014,work-compony:WW 企业