用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式,即Prototype,是指创建新对象的时候,根据现有的一个原型来创建。
举例:如果有一个String[]
数组,想再创建一个一模一样的String[]
数组,怎么写?
实际上创建过程很简单,就是把现有数组的元素复制到新数组。如果我们把这个创建过程封装一下,就成了原型模式。用代码实现如下:
// 原型:
String[] original = { "Apple", "Pear", "Banana" };
// 新对象:
String[] copy = Arrays.copyOf(original, original.length);
对于普通类,如何实现原型拷贝?Java的Object
提供了一个clone()
方法,它的意图就是复制一个新的对象出来,我们需要实现一个Cloneable
接口来标识一个对象是“可复制”的:
package com.learn.parattern.prototype;
public class Student implements Cloneable{
private int id;
private String name;
private int score;
@Override
public Object clone(){
Student student=new Student();
student.id=this.id;
student.name=this.name;
student.score=this.score;
return student;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return String.format("{Student: id=%s, name=%s, score=%s}@%s", this.id, this.name, this.score,
Integer.toHexString(hashCode()));
}
}
package com.learn.parattern.prototype;
public class test {
public static void main(String[] args) {
Student student=new Student();
student.setId(1);
student.setName("小明");
student.setScore(66);
Student student1= (Student) student.clone();
System.out.println(student);
//{Student: id=1, name=小明, score=66}@2503dbd3
System.out.println(student1);
//{Student: id=1, name=小明, score=66}@6f94fa3e
System.out.println(student==student1);
//false
}
}
使用的时候,因为clone()
的方法签名是定义在Object
中,返回类型也是Object
,所以要强制转型,比较麻烦;
实际上,使用原型模式更好的方式是定义一个copy()
方法,返回明确的类型:
public Student copy(){
Student student=new Student();
student.id=this.id;
student.name=this.name;
student.score=this.score;
return student;
}
注:
1.原型模式应用不是很广泛,因为很多实例会持有类似文件、Socket这样的资源,而这些资源是无法复制给另一个对象共享的,只有存储简单类型的“值”对象可以复制。
2.原型模式是根据一个现有对象实例复制出一个新的实例,复制出的类型和属性与原实例相同。