概述
原型模式的定义:以一个已经创建的实例作为原型,通过复制该对象来创建一个和原型相同或相似的新对象。
优点
1.复制在性能上比直接 new 一个对象更加优良。
2.可以使用深拷贝方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,可辅助实现撤销操作。
缺点
1.需要为每一个类配备一个克隆方法,对已有的类进行改造时,需要修改源代码,违背了“开闭原则”
2.在实现深克隆时需要编写较为复杂的代码,且当对象之间存在多重的嵌套引用时,需要对每一层对象对应的类都必须支持深克隆
应用场景
当创建新对象成本较高时或需要创建大量相同或相似的对象时
举例说明
一个类实现Coneable接口,重写clone方法即完成了一个最简单的原型模式
public class Student implements Cloneable{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
}
测试,debug看一下student1与student2的区别
可以看到student1与student2两个对象的name字段的内存地址是一样的,也就是两个对象引用了同一个name字段,这是因为实现cloneable接口属于浅拷贝
深拷贝与浅拷贝的区别
浅拷贝:如果原型对象的成员变量是基本数据类型(int、double、byte、boolean、char等),将复制一份给克隆对象;
如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址,通过覆盖Object类的clone()方法可以实现浅克隆
深拷贝:无论原型对象的成员变量是基本数据类型还是引用类型,都将复制一份给克隆对象,如果需要实现深克隆,可以通过序列化(Serializable)等方式来实现
原型模式是内存二进制流的拷贝,比new对象性能高很多
要实现深拷贝,要实现序列化接口Serializable
代码如下
public class Student implements Cloneable, Serializable{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
/**
* 深拷贝
* @return
* @throws IOException
*/
public Student deepClone() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
try {
Student copy = (Student) ois.readObject();
return copy;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
测试
name属性地址不同,两个对象都有属于自己的name字段,实现了深拷贝