原型模式概述:通过复制一个实例(原型)来创建新的对象。
使用场景:对象实例化创建过程比较复杂时,可以复制一个新的对象,在复制对象的基础上改变属性。
原型模式又分为深克隆(完全复制)和浅克隆(不完全复制)
浅克隆
在浅克隆中,如果原型对象的成员变量是值类型(如int、double、byte、boolean、char等基本数据类型,String由于其特殊性,和值类型效果一样),将复制一份给克隆对象;如果原型对象的成员变量是引用类型(如类、接口、数组等复杂数据类型),则复制的是地址给克隆对象。
实现: 克隆前,原型对象需要实现Cloneable接口,并重写clone()方法
1.实现Citation(原型对象)类,并实现Cloneable接口,重写clone()方法
package citation;
public class Citation implements Cloneable {
String str;
Student stu;
public String getName() {
return str;
}
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
public void setName(String str) {
this.str = str;
}
@Override
protected Citation clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Citation) super.clone();
}
}
2.实现原型对象的成员类Student
package citation;
public class Student {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.实现测试类Test
package citation;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建student实例stu
Student stu = new Student();
stu.setName("mingo");
// 创建原型实例citation
Citation citation = new Citation();
citation.setStu(stu);
// 通过原型实例克隆新对象
Citation citation1 = citation.clone();
// 输出原型实例以及克隆实例的学生姓名
System.out.println("原型实例学生:" + citation.getStu().getName() + "\n克隆实例的学生:" + citation1.getStu().getName());
}
}
结果:
1)修改原型中的stu,则克隆对象的stu也会随之改变
package citation;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建student实例stu
Student stu = new Student();
stu.setName("mingo");
// 创建原型实例citation
Citation citation = new Citation();
citation.setStu(stu);
// 通过原型实例克隆新对象
Citation citation1 = citation.clone();
// 输出原型实例以及克隆实例的学生姓名
System.out.println("修改前:\n"+"原型实例学生:" + citation.getStu().getName() + "\n克隆实例的学生:" + citation1.getStu().getName());
//修改原型对象中的stu
stu.setName("wang");
// 输出修改后的原型实例以及克隆实例的学生姓名
System.out.println("修改后:\n"+"原型实例学生:" + citation.getStu().getName() + "\n克隆实例的学生:" + citation1.getStu().getName());
}
}
运行结果:
2)如果想修改使得两个stu不同,则另外实例化一个stu对象设置给克隆对象。
//重新实例化一个student
Student stu1 = new Student();
stu1.setName("min");
citation1.setStu(stu1);
// 输出修改后的原型实例以及克隆实例的学生姓名
System.out.println("修改后2:\n"+"原型实例学生:" + citation.getStu().getName() + "\n克隆实例的学生:" + citation1.getStu().getName());
System.out.println("stu1==stu2?");
System.out.println((citation.getStu())==(citation1.getStu()));
}
运行结果: