定义
原型模式也是一种创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。
原型模式要求对象实现一个可以 “克隆” 自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过 new
实例化来创建对象。
优缺点
优点:可以动态地添加产品类而且对整体结构没有影响。
缺点:由于原型模式需要给每一个类都配备一个克隆的方法,这就需要在设计类时通盘考虑。因为在已有类的基础上添加 clon e操作比较困难。
实例
需求:
有一个学校需要维护学生信息,其中学校名称都是固定的,只有学生的姓名需要改变
学生对象定义:
public class Student implements Cloneable {
/**
* 学习名称
*/
private String schoolName;
/**
* 学生名称
*/
private String studentName;
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "学校名称:" + this.schoolName + "; 学生姓名:" + this.studentName;
}
}
逻辑实现:
public static void main(String[] args) throws CloneNotSupportedException {
Student student = new Student();
student.setSchoolName("浙江大学");
System.out.println("克隆前 >"+student.toString());
for (int i = 0; i < 10; i++) {
Student newStudent = (Student) student.clone();
newStudent.setStudentName("学生--" + i);
System.out.println("克隆中 >"+newStudent.toString());
}
System.out.println("克隆后 >"+student.toString());
}
控制台输出:
克隆前 >学校名称:浙江大学; 学生姓名:null
克隆中 >学校名称:浙江大学; 学生姓名:学生--0
克隆中 >学校名称:浙江大学; 学生姓名:学生--1
克隆中 >学校名称:浙江大学; 学生姓名:学生--2
克隆中 >学校名称:浙江大学; 学生姓名:学生--3
克隆中 >学校名称:浙江大学; 学生姓名:学生--4
克隆中 >学校名称:浙江大学; 学生姓名:学生--5
克隆中 >学校名称:浙江大学; 学生姓名:学生--6
克隆中 >学校名称:浙江大学; 学生姓名:学生--7
克隆中 >学校名称:浙江大学; 学生姓名:学生--8
克隆中 >学校名称:浙江大学; 学生姓名:学生--9
克隆后 >学校名称:浙江大学; 学生姓名:null
注意
以上代码有两个隐藏的风险:
- 上面的克隆只是浅克隆,深克隆需要自己实现克隆方法
- 反序列化时会重新生成一个对象,而不是之前的对象
那么要怎么解决呢,只需要我们自己实现下 clone
方法
@Override
protected Student clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
// 克隆其他对象属性
return student;
}
浅克隆和深克隆的区别
- 浅克隆:能复制变量,如果对象内还有对象,则只能复制对象的地址
- 深克隆:能复制变量,也能复制当前对象的内部对象