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

java设计模式-原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式。在java中,主要就是靠clone来复制对象,所以原型模式还是要先学习一下Cloneable这个接口。

浅克隆和深克隆

java中用基础类型和引用类型。基础类型就是String,Integer这些类型,引用类型就是对象,数组这些。

拿简历来说,简历里面有个人信息,和工作经历。个人信息包括姓名,年龄,性别,个人信息属于简历类里面的属性,工作经历则是另外一个类,在简历类里面引用它。

浅克隆就是只复制了个人信息,工作经历由于是引用对象,所以如果只是克隆简历类,则不管复制几个简历,里面的工作经历都只是引用同个对象。所以深克隆就是将工作经历也进行克隆。下面来看看代码

实现Cloneable接

WorkExperience.java

public class WorkExperience implements Cloneable{
	private String workDate;
	private String company;
	
	@Override
	protected Object clone()  {
		Object object =null;
		try {
			object = super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return object;
	}
	public WorkExperience(String workDate, String company) {
		super();
		this.workDate = workDate;
		this.company = company;
	}
	get和set方法...

Resume.java(简历类)

public class Resume implements Cloneable{
	private String name;
	private String sex;
	private String age;
	
	private WorkExperience workExperience;

	@Override
	protected Object clone()  {
		Resume clone = null ;
		try {
            //对resume克隆
			clone =(Resume)super.clone();
            //对workExperience克隆,如果没有,就是浅克隆
			clone.setWorkExperience((WorkExperience) workExperience.clone());
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return clone;
	}
	
	public Resume(String name, String sex, String age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	get和set方法...

调用

	public static void main(String[] args) {
		Resume prototype = new Resume("小张", "3", "男");
		WorkExperience workExperience = new WorkExperience("1996","company");
		prototype.setWorkExperience(workExperience);
		
		Resume clone1 = (Resume)prototype.clone();
		
		System.out.println(prototype+"\n"+clone1+"\n");
		System.out.println(prototype.getWorkExperience()+"\n"+
		clone1.getWorkExperience());
	}

打印结果

designPattern.prototypePattern.Resume@7852e922
designPattern.prototypePattern.Resume@4e25154f

designPattern.prototypePattern.WorkExperience@70dea4e
designPattern.prototypePattern.WorkExperience@5c647e05

可以看到结果,复制出来的clone1,包括里面的WorkExperience对象都和原来的不一样,实现了深度克隆。

这里的WorkExperience和Resume都实现了Cloneable接口,在克隆resume类的时候对resume和workexperience都进行克隆。

实现Serializable接口

除了Cloneable接口,还可以实现Serializable接口。

WorkExperience.java只需要声明实现接口就好,去掉clone方法,其余不需要变。

public class WorkExperience implements Serializable{}

Resume.java

public class Resume implements Serializable{

	private static final long serialVersionUID = 7260158333965490347L;
	private String name;
	private String sex;
	private String age;
	
	private WorkExperience workExperience;
	
	protected Object clone()  {
		Object object =null;
		try {
			//将对象写入流中
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream ooStream = new ObjectOutputStream(bos);
			ooStream.writeObject(this);
			
			//从流中读出对象
			ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
			ObjectInputStream oIStream = new ObjectInputStream(bis);
			object = oIStream.readObject();
		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return object;
	}
	
	public Resume(String name, String sex, String age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
}

调用和打印结果都一样。就不贴出来了。

这里是用序列化(Serialization)方式来实现克隆,可以看到WorkExperience和Resume都实现了Serialization接口。

序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。

可以看到,深克隆会比较复杂,耗时。对于浅克隆的缺点:引用对象会指向同一个地址,一个对象改变,另一个对象也会改变。如果我们的应用场景不会去更新这个引用对象,那么浅克隆也是可以接受的。或者如果只有部分对象会发生改变,我们可以使用浅克隆来克隆所有对象,然后再单独去深度克隆那些会发生改变的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值