继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用!
4.5 原型模式
4.5.1 概述
用已创建实例作为原型,通过复制该原型对象来创建一个和原型对象一样的新对象
4.5.2 结构
- 抽象原型类:规定具体原型对象必须实现的clone()方法
- 具体原型类:实现抽象原型类中方法,是可被复制对象
- 访问类:使用具体原型类中clone方法来复制新对象
4.5.3 分类
- 浅克隆:创建对象,新对象属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向对象内存地址
- 深克隆:创建对象,属性中引用其他对象会被克隆,不再指向原有对象地址
注:
- Java中的Object类提供
clone()
方法实现浅克隆 - Java 中的 Cloneable 接口是抽象原型类,而实现了 Cloneable 接口的子实现类就是具体的原型类
4.5.4 验证浅克隆
- 验证Object类
clone()
实现浅克隆 - 具体原型
public class RealizeType implements Cloneable{
public RealizeType(){
System.out.println("具体原型创成功");
}
@Override
public RealizeType clone() throws CloneNotSupportedException {
System.out.println("克隆具体原型成功!");
return (RealizeType) super.clone();
}
}
- 测试
public static void main(String[] args) throws Exception {
// 创建具体原型对象
RealizeType realizeType = new RealizeType();
// 克隆
RealizeType clone = realizeType.clone();
System.out.println("原型对象与克隆对象是否是同一个对象?" + (realizeType == clone ));
}
结果符合预期
# 注意:
java.lang.object规范中对clone方法的约定:
- 对任何的对象x,都有x.clone() !=x 因为克隆对象与原对象不是同一个对象
- 对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样
- 如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立
4.5.5 使用场景
- 对象创建比较复杂,可用原型模式快速创建对象
- 性能和安全要求高
4.5.6 案例
- 学生类
public class Student{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 引用类
public class Citation implements Cloneable {
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
public Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
public void show()
{
System.out.println(student.getName() + "是好学生");
}
}
- 测试结果如图
public static void main(String[] args) throws CloneNotSupportedException {
Citation citation = new Citation();
Student student = new Student();
student.setName("张三");
citation.setStudent(student);
Citation clone = citation.clone();
clone.getStudent().setName("李四");
citation.show();
clone.show();
}
4.5.7 深克隆
5.7.1 序列化与反序列化
- 使用浅克隆案例
- 给Citation类和学生类实现序列化接口
- 修改测试类
public static void main(String[] args) throws Exception {
Citation citation = new Citation();
Student student = new Student();
student.setName("张三");
citation.setStudent(student);
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./b.txt"));
outputStream.writeObject(citation);
outputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("./b.txt"));
Citation citation1 = (Citation) objectInputStream.readObject();
objectInputStream.close();
citation.show();
citation1.getStudent().setName("李四");
citation1.show();
}
结果
5.7.2 重写clone方法
- 重写Citation类方法
@Override
public Citation1 clone() throws CloneNotSupportedException {
Student student1 = new Student();
student1.setName(student.getName());
Citation1 citation1 = new Citation1();
citation1.setStudent(student1);
return citation1;
}
- 测试
public static void main(String[] args) throws CloneNotSupportedException {
Citation1 citation = new Citation1();
Student student = new Student();
student.setName("张三");
citation.setStudent(student);
Citation1 clone = citation.clone();
clone.getStudent().setName("李四");
citation.show();
clone.show();
}