原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。
原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。
原型模式的核心是一个clone()方法,通过该方法进行对象拷贝,Java提供了一个Clonnable接口来表示这个对象是可以拷贝的。方法是覆盖clone(),此方法每个类中都有,因为它是Java中所有类的老祖宗Object中的方法。
在进行对象拷贝的时候,该类的构造函数并没有执行,因为Object中的clone()方法的原理是从堆内存中以二进制流的方式进行拷贝,重新分配一个内存块,所以构造函数并不会被执行
例子:假设有一个person类.存在两个实例张三和李四,但是因为张三和李四有些属性是相像的。所以不用通过张三这个原型来copy出一个李四的实例
1. person类代码
import java.util.ArrayList;
import java.util.List;
public class Person implements Cloneable{
private String name;
private int age;
private char gender;
private double height;
private double weight;
private ArrayList<String> readBooks = new ArrayList<String>();//读过的书
public Person() {
System.out.println("构造--person--开始执行.....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public List<String> getReadBooks() {
return readBooks;
}
public void setReadBooks(String readBook) {
this.readBooks.add(readBook);
}
public void sayHello() {
System.out.println("my name :" + name + "--my age: " + age
+ "--my gender: " + gender + "--读过的书:" + this.readBooks);
}
@Override
public Object clone() throws CloneNotSupportedException {
Person person = null;
person = (Person) super.clone();
return person;
}
}
2. 运行类
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
//实例化一个张三的对象
Person zhangsan = new Person();
zhangsan.setName("张三");
zhangsan.setAge(11);
zhangsan.setGender('男');
//通过张三复制出来一个李四的对象
Person lisi = (Person) zhangsan.clone();
//修改一下名字
lisi.setName("李四");
//李四读过一本叫心理学的书
lisi.setReadBooks("心理学");
//张三的自我介绍
zhangsan.sayHello();
System.out.println("-----------------");
//李四的自我介绍
lisi.sayHello();
}
}
运行结果:
构造--person--开始执行.....
my name :张三--my age: 11--my gender: 男--读过的书:[心理学]
-----------------
my name :李四--my age: 11--my gender: 男--读过的书:[心理学]
我们分析这个结果,发现构造函数只执行了一次,但是张三本来没有读过心理学的书,但程序执行的时候
发现,张三读过的书中有这个值。原因就是克隆时的深克隆和浅克隆。上面代码是浅克隆。
将clone()方法改成如下
public Object clone() throws CloneNotSupportedException {
Person person = null;
person = (Person) super.clone();
person.readBooks = (ArrayList<String>) this.readBooks.clone();//深度克隆
return person;
}
再执行,结果如下:
构造--person--开始执行.....
my name :张三--my age: 11--my gender: 男--读过的书:[]
-----------------
my name :李四--my age: 11--my gender: 男--读过的书:[心理学]
这样就完全实现了两个对象间的隔离。
菜鸟,HY大神拍砖,共同进步,上次已经有大神拍了感激不尽。