原型模式(Prototype)
程序员文章站
2022-06-12 21:47:50
...
原型模式(Prototype)
定义:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
工作原理:
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
理解:
原型模式,顾名思义,通过一个原型模板,依葫芦画瓢得到另一个新的对象。
即通过一个已经存在的对象,复制出更多的具有与此对象具有相同类型的新的对象。
Java中对象的复制可以通过克隆完成。所以我们需先对克隆有所了解。
Java中有基本数据类型和引用类型之分。基本数据类型存放的是数值本身,引用类型存放的是数据的引用(类似指针)。
1、浅复制
基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。String是class对象,所以为引用类型,但因为String是final的且加之JVM对String优化,因此修改了克隆对象的String类型值后,原型对象的String类型之不会发生改变。Object的clone()方法默认为浅复制。
public class ShallowClone {
public static void main(String[] args) throws CloneNotSupportedException {
Course course = new Course("语文");
Student stuA = new Student();
stuA.setAge(11);
stuA.setName("张三");
stuA.setCourse(course);
System.out.println("修改值前:");
System.out.println("stuA:"+ stuA.toString());
Student stuB = stuA.clone();
System.out.println("stuB:"+ stuB.toString());
stuB.setAge(22);
stuB.setName("李四");
stuB.setCourseName("数学");
System.out.println("\n\n修改值后:");
System.out.println("stuA:"+ stuB.toString());
System.out.println("stuB:"+ stuA.toString());
}
}
class Student implements Cloneable{
private int age;
private String name;
private Course course;
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student)super.clone();
}
@Override
public String toString() {
return "年龄:" + this.age + "\t姓名:" + this.getName() + "\t选修课程:"+ this.getCourse().getName();
}
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;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
public void setCourseName(String name) {
this.course.setName(name);
}
}
class Course{
private String name;
public Course(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
打印结果:
修改值前:
stuA:年龄:11 姓名:张三 选修课程:语文
stuB:年龄:11 姓名:张三 选修课程:语文
修改值后:
stuA:年龄:22 姓名:李四 选修课程:数学
stuB:年龄:11 姓名:张三 选修课程:数学
对于引用类型,原型对象和克隆对象指向了相同的引用。所以修改引用类型的值后,原型对象和克隆对象都会随之改变。
2、深复制
深复制是完全拷贝,克隆对象与原型对象的引用类型的值都指向了不同的实例,因此修改克隆或原型的引用类型值也不会相互影响。上述实例只需要修改clone方法,即可改为深复制。
package prototype.deep;
public class DeepClone {
public static void main(String[] args) throws CloneNotSupportedException {
Course course = new Course("语文");
Student stuA = new Student();
stuA.setAge(11);
stuA.setName("张三");
stuA.setCourse(course);
System.out.println("修改值前:");
System.out.println("stuA:"+ stuA.toString());
Student stuB = stuA.clone();
System.out.println("stuB:"+ stuB.toString());
stuB.setAge(22);
stuB.setName("李四");
stuB.setCourseName("数学");
System.out.println("\n\n修改值后:");
System.out.println("stuA:"+ stuB.toString());
System.out.println("stuB:"+ stuA.toString());
}
}
class Student implements Cloneable{
private int age;
private String name;
private Course course;
@Override
protected Student clone() throws CloneNotSupportedException {
Student stu = (Student)super.clone();
Course cou = new Course(stu.getCourse().getName());
stu.setCourse(cou);
return stu;
}
@Override
public String toString() {
return "年龄:" + this.age + "\t姓名:" + this.getName() + "\t选修课程:"+ this.getCourse().getName();
}
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;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
public void setCourseName(String name) {
this.course.setName(name);
}
}
class Course{
private String name;
public Course(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
打印:
修改值前:
stuA:年龄:11 姓名:张三 选修课程:语文
stuB:年龄:11 姓名:张三 选修课程:语文
修改值后:
stuA:年龄:22 姓名:李四 选修课程:数学
stuB:年龄:11 姓名:张三 选修课程:语文
上一篇: 基于vue v-for 多层循环嵌套获取行数的方法
下一篇: 水痘的四大护理方法 水痘的护理原则