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.

总结:

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

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

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

  

  

  

  

  

    

时间: 2024-08-28 16:34:38

Java 设计模式:原型Prototype的相关文章

Java 实现原型(Prototype)模式

public class BaseSpoon implements Cloneable {//spoon 匙, 调羹 String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected BaseSpoon clone() throws CloneNotSupportedException { System.o

Java设计模式——原型模式

概述 原型模式是为了解决一些不必要的对象创建过程.当Java JDK中提供了Cloneable接口之后,原型模式就变得异常的简单了.虽然由于Cloneable的引入使用程序变得更简单了,不过还是有一些需要说明和注意的东西在里面的.文本就详细讲解一下这些注意事项吧. 版权说明 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Coding-Naga发表日期: 2016年3月3日链接:http://blog.csdn.net/lemon_tree12138/article/d

java设计模式 - 原型(干货)

深度讲解23种设计模式,力争每种设计模式都刨析到底.废话不多说,开始第二种设计模式 - 原型. 一.为什么有原型模式 当一个类需要克隆的时候,我们总不希望new一个对象,然后逐个属性去设置值. 这个时候,我们亟需一种 高效的对象copy方法,原型设计模式应运而生. 二.原型设计模式写法 原型设计模式实现: public class Person implements Cloneable { private String userName; private String sex; private

Java 设计模式——原型模式(Prototype)

原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象. 原型模式有简单形式和登机形式两种表现 形式. 简单形式的原始模型模式 简单形式UML类图如下: 原型模式的角色有 客户端角色(ClientPro): 抽象原型角色(ProtoType): 具体原型角色(ConcreteProtoType):被复制的对象 代码如下: public interface ProtoType { /** * 根据自身克隆出新的对象 * @aut

java设计模式-原型(prototype)

有时候创建对象是需要耗费很多资源,但是每个对象之间又有大量的重复.我们可以选择在创建好一个对象后,以之作为模板克隆出其他对象,稍作修改,即可用于其他地方. 需要实现Cloneable接口,重写clone()方法.其实就是调用的Object类的clone()方法. 克隆对象只是复制了原对象的数据,每个对象还是独立的,他们的内存地址不同. /** * Created by wangbin10 on 2018/5/18. */ public class Prototype2 implements Cl

java设计模式---原型模式

原型模式也是创建型的设计模式,通过拷贝原型创建新的对象,理解原型模式必须理解java中的浅复制和深复制.复制也称为克隆.会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型.其余的都是浅拷贝. 浅克隆:浅克隆仅仅克隆所考虑的对象,而不克隆它所引用的对象. 深克隆:深克隆不仅克隆所考虑的对象,也克隆它所引用的对象. 它的核心是就是原型类Prototype.Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接

JAVA 设计模式 原型模式

用途 原型模式 (Prototype) 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式是一种创建型模式. 结构 图-原型模式结构图 Prototype: 声明一个克隆自身的接口.ConcretePrototype: 实现克隆自身的具体操作.Client: 调用 Prototype 来克隆自身,从而创建一个新对象. 应用场景 当要实例化的类是在运行时刻指定时,例如,通过动态装载.为了避免创建一个与产品类层次平行的工厂类层次时.当一个类的实例只能有几个不同状态组合中的一种

Objective-C设计模式——原型Prototype(对象创建)

1.原型 原型设计模式所谓原型设计模式,其实就是对象复制,这个特性在所有语言基本上都是存在的. 我们知道在OC中,对象赋值其实是对对象的引用复制,其实就是相当于C语言中的指针.创建了一个新的变量,但是还是指向的同一块内存地址. 所以一旦一个引用改变了该对象的属性,那么其他指向该对象的引用全部都会发生变化. 有时候我们并不像要这样做,我们希望重新创建一个和赋值对象一模一样的一个对象.比如我们写游戏的时候创建了一个enemy对象并对其复杂的行走路径进行了自定义,此时我们想要在创建一个.但是再次创建时

设计模式--原型(Prototype)模式

写这些也许有人认为“为了模式而模式”.Insus.NET所想到的,每个大师成为大师之前,也许都得这样做. 走路,从小就开始学,直至现在,谁还不是为了走路而走路?一直重复着...... 很多人没有分享自己的经验,分享自己的过程,分享这东西,它不会因为分享而变少了...... 感动的故事,是因为分享了历程而让人感动...... 设计模式,在ASP.NET开发过程中,确实很多环境应用得到,也许只因为时间与效率问题,使用了最直接的方法来解决了.往往给以来的维护带来了繁杂变得难以进行. 进入主题,先看看这

克隆复制可使用原型( Prototype)设计模式

今天有学习设计模式的原型(Prototype)<设计模式--原型(Prototype)模式>http://www.cnblogs.com/insus/p/4152773.html .为了加强了解与认识,现再做一个练习. 创建一个原型接口: 创建一个用户控件,并实现接口: 现在网页中有一个按钮,用户点一点这个铵钮,能动态添加这个用户控件,每点击一次,克隆复制一个: 演示: 源代码下载:http://download.cnblogs.com/insus/CSharpNET/uc_prototype