原型模式:可以通过一个原型对象,克隆出多个一模一样的对象,克隆对象和原型对象虽然所属类型是一致的,但是地址不同!
就像双胞胎一样,虽然一模一样,但是是两个独立的个体啊!
我看到上面的定义,我就产生了为什么,就为什么需要多个一模一样的对象,我感觉没啥用啊?后面发现是有用的,这些还是得结合实例来看!
谈到了原型模式:就必须知道,深克隆和浅克隆,他们两者的主要区别是在于是否支持引用数据类型成员变量的复制,
一:浅克隆: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
}
}