标签:
原型模式Prototype
原型模式也是一种对象创建的模式,主要作用是通过拷贝已有对象来生成新对象。它的好处是在实例化对象时不用每一次都使用新建,这样如果在新建对象比较耗时的情况下可以提高程序的运行效率。
原型模式中的拷贝分为浅拷贝和深拷贝
浅拷贝: 对对象中的值类型进行拷贝,对引用类型不拷贝还是指向相同的引用;
深拷贝: 对对象中的值类型进行拷贝,对引用类型也拷贝;
示例:
现有简历类,类的属性有姓名、年龄和工作经验,工作经验为引用类型包括公司名称和工作时间
浅拷贝代码如下:
工作经验类 WorkExperience
class WorkExperience
{
private String companyName;
private int years;
public WorkExperience (String cname , int years )
{
this.companyName = cname ;
this.years = years;
}
public String getCompanyName()
{
return companyName;
}
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
public int getYears()
{
return years;
}
public void setYears(int years)
{
this.years = years;
}
}
简历类 Resume
class Resume implements Cloneable
{
private WorkExperience workExperience ;
private String name ;
private int age ;
public Resume(WorkExperience workExperience, String name, int age)
{
super();
this.workExperience = workExperience;
this.name = name;
this.age = age;
}
public WorkExperience getWorkExperience()
{
return workExperience;
}
public void setWorkExperience(WorkExperience workExperience)
{
this.workExperience = workExperience;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public Object clone()
{
try
{
return super.clone(); //直接调用父类的clone方法
}
catch (CloneNotSupportedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return null ;
}
}
}
运行测试1:创建两个工作经验类we1和we2,创建简历类r1 并通过拷贝创建简历类r2.通过set方法修改简历r2的姓名、年龄和工作经验
public class ProtoType
{
public static void main (String args[])
{
WorkExperience we1 = new WorkExperience("公司A", 2);
WorkExperience we2 = new WorkExperience("公司B", 3);
Resume r1 = new Resume(we1, "小张", 24);
Resume r2= (Resume)r1.clone() ;
r2.setName("小李");
r2.setAge(30);
r2.setWorkExperience(we2);
System.out.println(r1.getName()+r1.getAge()+"岁,工作经验"+r1.getWorkExperience().getCompanyName()+","+r1.getWorkExperience().getYears()+"年");
System.out.println(r2.getName()+r2.getAge()+"岁,工作经验"+r2.getWorkExperience().getCompanyName()+","+r2.getWorkExperience().getYears()+"年");
}
}
运行结果如下
小张24岁,工作经验公司A,2年 小李30岁,工作经验公司B,3年
简历类r2 通过set方法修改属性值后未影响r1.
运行测试2:创建一个工作经验类we,创建简历类r1并通过克隆创建简历类r2 。r2通过set方法修改属性值name、age,并通过getWorkExperience()获取工作经验类后修改工作经验。代码如下
public class ProtoType
{
public static void main (String args[])
{
WorkExperience we = new WorkExperience("公司A", 2);
Resume r1 = new Resume(we, "小张", 24);
Resume r2= (Resume)r1.clone() ;
r2.setName("小李");
r2.setAge(30);
r2.getWorkExperience().setCompanyName("公司B");
r2.getWorkExperience().setYears(3);
System.out.println(r1.getName()+r1.getAge()+"岁,工作经验"+r1.getWorkExperience().getCompanyName()+","+r1.getWorkExperience().getYears()+"年");
System.out.println(r2.getName()+r2.getAge()+"岁,工作经验"+r2.getWorkExperience().getCompanyName()+","+r2.getWorkExperience().getYears()+"年");
}
}
运行结果
小张24岁,工作经验公司B,3年 小李30岁,工作经验公司B,3年
简历r2修改工作经验后简历r1中的工作经验也同样被修改了。这是由于浅拷贝中关于引用的拷贝是只拷贝了应用地址,r1和r2中指向了相同的we引用。
深拷贝:
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。
工作经验类同样实现 Cloneable 接口
class WorkExperience implements Cloneable
{
private String companyName;
private int years;
public WorkExperience (String cname , int years )
{
this.companyName = cname ;
this.years = years;
}
public String getCompanyName()
{
return companyName;
}
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
public int getYears()
{
return years;
}
public void setYears(int years)
{
this.years = years;
}
public Object clone()
{
try
{
return super.clone(); //直接调用父类的clone方法
}
catch (CloneNotSupportedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return null ;
}
}
}
简历类:简历类中的修改是通过拷贝设置工作经验
class Resume implements Cloneable
{
private WorkExperience workExperience ;
private String name ;
private int age ;
public Resume(WorkExperience workExperience, String name, int age)
{
super();
this.workExperience = workExperience;
this.name = name;
this.age = age;
}
public WorkExperience getWorkExperience()
{
return workExperience;
}
public void setWorkExperience(WorkExperience workExperience)
{
this.workExperience = workExperience;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public Object clone()
{
Resume r = null;
try
{
r= (Resume)super.clone();
r.setWorkExperience((WorkExperience)workExperience.clone()); //通过拷贝设置工作经验
return r;
}
catch (CloneNotSupportedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return null ;
}
}
}
运行测试:
同运行测试2中的代码相同
public class ProtoType
{
public static void main (String args[])
{
WorkExperience we = new WorkExperience("公司A", 2);
Resume r1 = new Resume(we, "小张", 24);
Resume r2= (Resume)r1.clone() ;
r2.setName("小李");
r2.setAge(30);
r2.getWorkExperience().setCompanyName("公司B");
r2.getWorkExperience().setYears(3);
System.out.println(r1.getName()+r1.getAge()+"岁,工作经验"+r1.getWorkExperience().getCompanyName()+","+r1.getWorkExperience().getYears()+"年");
System.out.println(r2.getName()+r2.getAge()+"岁,工作经验"+r2.getWorkExperience().getCompanyName()+","+r2.getWorkExperience().getYears()+"年");
}
}
运行结果
小张24岁,工作经验公司A,2年 小李30岁,工作经验公司B,3年
r2修改工作经验后没有影响r1.
总结:
原型模式主要用到的技术就是克隆,这样如果是在创建对象比较费时是可以提高程序的效率;
深拷贝相对于浅拷贝来说要花费更多的内存开销,具体使用那种拷贝方式可以视情况而定;
深拷贝和浅拷贝可以结合使用(延迟拷贝)这样既可以提高效率也可以进行深拷贝。
标签:
原文地址:http://www.cnblogs.com/zxlong/p/4121608.html