设计模式之原型模式(5)

原型模式:可以通过一个原型对象,克隆出多个一模一样的对象,克隆对象和原型对象虽然所属类型是一致的,但是地址不同!
就像双胞胎一样,虽然一模一样,但是是两个独立的个体啊!

我看到上面的定义,我就产生了为什么,就为什么需要多个一模一样的对象,我感觉没啥用啊?后面发现是有用的,这些还是得结合实例来看!

谈到了原型模式:就必须知道,深克隆和浅克隆,他们两者的主要区别是在于是否支持引用数据类型成员变量的复制, 
一:浅克隆:Object.clone(), 记得实现Cloneable标记接口
在浅克隆中, 如果原型对象的成员变量是值类型, 将复制一份给克隆对象; 如果原型对象的
成员变量是引用类型, 则将引用对象的地址复制一份给克隆对象, 也就是说原型对象和克隆
对象的成员变量指向相同的内存地址。 简单来说, 在浅克隆中, 当对象被复制时只复制它本
身和其中包含的值类型的成员变量, 而引用类型的成员对象并没有复制


 

二:深克隆(序列化技术)记得实现Serializable接口

 

 
三:下面通过周报的案例,演示浅克隆和深克隆
3.1浅克隆代码:

具体原型类

//周报: 具体原型类
public class WeeklyLog implements Cloneable{
	private Attachment attachment;//附件
	private String name;
	private String date;
	private String content;
	public Attachment getAttachment() {
		return attachment;
	}
	public void setAttachment(Attachment attachment) {
		this.attachment = attachment;
	}
	//..getter/setter
	@Override
	protected WeeklyLog clone() throws CloneNotSupportedException {
		return (WeeklyLog) super.clone();
	}
}

Attachment 类

public class Attachment {

}

测试类

public class Client {

	public static void main(String[] args) throws CloneNotSupportedException {
		
		WeeklyLog log_previous,log_new;
		log_previous = new WeeklyLog();
		log_previous.setAttachment(new Attachment());
		log_new = log_previous.clone();
		
		System.out.println(log_previous.getClass() == log_new.getClass());//同一类型,都是WeeklyLog类!
		System.out.println("周报是否相同:"+(log_previous == log_new));//false: 同一类型,不对对象!
		System.out.println("附件是否相同:"+(log_previous.getAttachment() == log_new.getAttachment()));//true,因为是浅克隆,所以如果是引用数据类型的话,会将其地址复制过去,所以指向的是同一个对象!
	}
}

3.2深克隆代码:
具体原型类

//周报: 具体原型类
public class WeeklyLog implements Serializable{
	private Attachment attachment;//附件
	private String name;
	private String date;
	private String content;
	public Attachment getAttachment() {
		return attachment;
	}
	public void setAttachment(Attachment attachment) {
		this.attachment = attachment;
	}
	//...getter/setter

	public WeeklyLog deepClone() throws IOException, ClassNotFoundException {
			//这里为什么使用ByteArrayOutputStream呢? 就是临时存储在内存中,如果不使用它的话,就得从文件中读取,还要在系统中创建一个临时文件就有点多余!
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(this);
			
			//从内存中读取
			ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bis); //参数是一个InputStream(抽象类): 里氏替换原则!
			Object readObject = ois.readObject();
			return (WeeklyLog) readObject;
	}
}

Attachment 类

public class Attachment implements Serializable{

}

测试类

//都得实现Serializable接口
public class Client {

	public static void main(String[] args) throws ClassNotFoundException, IOException {
		
		//具体原型类
		WeeklyLog log_previous, log_new;
		log_previous = new WeeklyLog();
		log_previous.setAttachment(new Attachment());
		
		log_new = log_previous.deepClone();
		System.out.println("周报是否相同:"+(log_previous == log_new));//false
		System.out.println("附件是否相同:"+(log_previous.getAttachment() == log_new.getAttachment()));//false,不再是赋值引用类型的地址了,所以是false
	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值