原型模式

原型模式

定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
实现的效果就是从一个对象再创建另一个可定制的对象,而且不需要知道任何创建的细节。一般在初始化的信息不发生变化的情况下,克隆是最好的办法。既隐藏了对象创建的细节,对性能也有大大的提高。不用重新初始化对象,而是动态的获得对象运行时的状态。

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公司
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值