首页 > 代码库 > Java 设计模式:原型Prototype

Java 设计模式:原型Prototype

原型模式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.

 

总结:

  原型模式主要用到的技术就是克隆,这样如果是在创建对象比较费时是可以提高程序的效率;

  深拷贝相对于浅拷贝来说要花费更多的内存开销,具体使用那种拷贝方式可以视情况而定;

  深拷贝和浅拷贝可以结合使用(延迟拷贝)这样既可以提高效率也可以进行深拷贝。

  

 

 

  

  

 

  

 

 

  

 

 

 

    

Java 设计模式:原型Prototype