欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

原型模式(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	姓名:张三	选修课程:语文