简介
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。
优点: 1、性能提高。 2、逃避构造函数的约束。
缺点: 1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 2、必须实现 Cloneable 接口。
浅拷贝与深拷贝
在实现Cloneable接口时,进行拷贝对象,效率比构造函数要高,也避免了构造传参的麻烦。
拷贝对象分为浅拷贝和深拷贝,默认的Object.clone()是浅拷贝。浅拷贝只能复制基本数据类型和基本数据类型的包装类,以及特殊的String类。如果是复杂的引用类型,浅拷贝会直接拷贝引用,如果原始对象修改了引用对象内部属性的值,所有拷贝的对象的值会跟着变,这会引发安全问题。
也就是说,当对象的属性中包含复杂的对象时,要使用深拷贝,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。
简单的深拷贝实现是,在对象的每一层中都调用clone方法,即可实现深拷贝,即每层对象浅拷贝 = 深拷贝。如果对象层次比较多,调用clone会很复杂,这时可以使用序列化,再反序列化回来的方式进行深拷贝,另外通过序列化为json字符串,然后从json字符串转回来也是比较常用的方式。
应用实例
克隆羊,通过clone方法进行复制多个对象,这里使用浅拷贝就可以。
package com.mori.design.pattern.prototype;
/**
* 羊
* @author mori
*/
public class Sheep implements Cloneable{
private String name;
private Integer age;
private String color;
public Sheep(String name, Integer age, String color) {
super();
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
/**
* 克隆该实例,使用默认的clone方法来完成
*/
@Override
public Sheep clone() {
Sheep sheep = null;
try {
sheep = (Sheep)super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return sheep;
}
@Override
public String toString() {
return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
}
}
测试代码如下
public void testSheep(){
Sheep sheep = new Sheep("小样", 12, "白色");
Sheep sheep2 = sheep.clone();
Sheep sheep3 = sheep.clone();
Sheep sheep4 = sheep.clone();
System.out.println(sheep);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
}
控制台输出:
Sheep [name=小样, age=12, color=白色]
Sheep [name=小样, age=12, color=白色]
Sheep [name=小样, age=12, color=白色]
Sheep [name=小样, age=12, color=白色]