1.介绍
1.1.定义
允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。即用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。
1.2.工作原理
将原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。即用基类Object的clone()方法或序列化。
1.3.结构与模式
原型模式包含以下主要角色
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
结构图
2.代码实现
2.1.浅拷贝
public class CloneableSheep implements Cloneable{
private String name;
private Integer age;
private CloneableSheep friend;
public CloneableSheep(String name, Integer age, CloneableSheep friend) {
this.name = name;
this.age = age;
this.friend = friend;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public CloneableSheep getFriend() {
return friend;
}
public void setFriend(CloneableSheep friend) {
this.friend = friend;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", friend=" + friend +
'}';
}
}
客户端
@Test
public void test() throws Exception {
CloneableSheep cs1 = new CloneableSheep("多利", 3, new CloneableSheep("彭彭", 2, null));
CloneableSheep cs2 = (CloneableSheep) cs1.clone();
System.out.println("cs1 hashcode:" + cs1.hashCode() + ",cs1 friend hashcode:" + cs1.getFriend().hashCode());
System.out.println("cs2 hashcode:" + cs2.hashCode() + ",cs2 friend hashcode:" + cs2.getFriend().hashCode());
}
结果输出
cs1 hashcode:721748895,cs1 friend hashcode:1642534850
cs2 hashcode:1724731843,cs2 friend hashcode:1642534850
2.2.深拷贝
public class SerializableSheep implements Serializable {
private String name;
private Integer age;
private SerializableSheep friend;
public SerializableSheep(String name, Integer age, SerializableSheep friend) {
this.name = name;
this.age = age;
this.friend = friend;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public SerializableSheep getFriend() {
return friend;
}
public void setFriend(SerializableSheep friend) {
this.friend = friend;
}
public Object clone() {
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
// 序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
assert bos != null;
bos.close();
assert oos != null;
oos.close();
assert bis != null;
bis.close();
assert ois != null;
ois.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Override
public String toString() {
return "SerializableSheep{" +
"name='" + name + '\'' +
", age=" + age +
", friend=" + friend +
'}';
}
}
客户端
@Test
public void test() throws Exception {
SerializableSheep ss1 = new SerializableSheep("山姆", 3, new SerializableSheep("乐乐", 2, null));
SerializableSheep ss2 = (SerializableSheep) ss1.clone();
System.out.println("ss1 hashcode:" + ss1.hashCode() + ",ss1 friend hashcode:" + ss1.getFriend().hashCode());
System.out.println("ss2 hashcode:" + ss2.hashCode() + ",ss2 friend hashcode:" + ss2.getFriend().hashCode());
}
结果输出
ss1 hashcode:204349222,ss1 friend hashcode:515132998
ss2 hashcode:1279149968,ss2 friend hashcode:59559151
3.应用场景
使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。