赞
踩
原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。原型模式包含以下角色:
原型模式的克隆分为浅克隆和深克隆
Java中的Object类中提供了clone()方法来实现浅克隆。Cloneable接口是Java提供的抽象原型类而实现了Cloneable接口的子实现类就是具体原型类
【案例】
同一个学校的三好学生奖状除了获奖姓名不同,其他都相同,可以使用原型模式复制出多个三好学生奖状,然后修改奖状上的学生姓名即可
public class Citation implements Cloneable {
private String name; //三好学生的姓名
public String getName(){return name;}
public void setName(String name) {this.name = name;}
public void show(){System.out.println(name+"同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状");}
public Citation clone() throws CloneNotSupportedException {
return (Citation)super.clone();
}
}
public class Test{
public static void main(String[] args) throws CloneNotSupportedException {
Citation citation = new Citation();//创建原型对象
Citation clone = citation.clone();//复制原型对象
citation.setName("张三");
clone.setName("李四");
citation.show();//张三同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状
clone.show();//李四同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状
}
}
对于浅拷贝来说,具体原型对象的属性只能是基本数据类型和String类型,如果换成其他数据类型会发生什么呢
public class Citation implements Cloneable{ private Student student; public void setStudent(Student student) { this.student = student; } public Student getStudent() { return student; } public void show(){ System.out.println(student.getName()+"同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状"); } protected Citation clone() throws CloneNotSupportedException { return (Citation)super.clone(); } } class CitationTest{ public static void main(String[] args) throws Exception { Citation citation = new Citation();//创建原型对象 Student student = new Student(); student.setName("张三"); citation.setStudent(student); Citation clone = citation.clone();//拷贝原型对象 clone.getStudent().setName("李四"); citation.show();//李四同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状 clone.show();//李四同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状 } } class Student{ private String name; public String getName() {return name;} public void setName(String name) {this.name = name;} }
为什么两个输出都是李四同学?
因为Object类中提供了clone()方法实现的是浅克隆,对于非基本类型属性仍指向原有属性所指向的内存地址,原型类中的student对象和克隆类中的对象是同一个对象,当修改克隆类的student对象时也会修改原型类中的student对象
深拷贝就能解决以上问题
深拷贝的两种实现方式
以上面浅拷贝存在问题代码为例,我们只需要重写clone()方法和给Student类实现Cloneable接口并重写clone()方法即可完成深拷贝
//重写clone()方法
public Citation clone() throws CloneNotSupportedException {
Citation deepClone = (Citation )super.clone();
deepClone.student = (Student) student.clone();
return deepClone;
}
//重写clone()方法后Student要实现Cloneable接口
class Student implements Cloneable{
//其他代码...(和上面一样)
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
以上面浅拷贝存在问题代码为例,在主方法中序列化具体原型对象然后反序列化即可
public static void main(String[] args) throws Exception { Citation citation = new Citation(); Student student = new Student(); student.setName("张三"); citation.setStudent(student); /*序列化对象*/ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"));//开启对象输出流 oos.writeObject(citation);//序列化对象 oos.close();//关闭对象输出流 /*反序列化对象*/ ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"));//开启对象输入流 Citation clone = (Citation ) ois.readObject();//反序列化对象 ois.close();//关闭对象输入流 clone.getStudent().setName("李四"); citation.show();//张三同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状 clone.show();//李四同学,在2022学年第一学期中表现优异,被评为三好学生,特颁此状 } //因为要序列化对象所以Student类和Citation类 class Citation implements Cloneable,Serializable{//代码...} class Student implements Serializable{//代码...}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。