一、概述
原型模式是指用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。原型模式是一种创建型的设计模式,分为深克隆和浅克隆。
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝他们自己来实施创建,即:对象.clone()
二、角色
抽象原型:它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是接口,抽象类甚至是一个具体的实现类
具体原型:它实现了抽象原型类中声明的克隆方法,在克隆方法中返回一个自己的克隆对象
客户类:在客户类中,使用原型对象只需要通过工厂方式创建或者直接new(实例化一个)原型对象,然后通过原型对象的克隆方法就能获得多个相同的对象。
三、栗子
1.浅克隆
1) Parent与Child类
public class Parent implements Cloneable {
private String name;
private Child child;
public Parent(String name, Child child) {
this.name = name;
this.child = child;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
@Override
public String toString() {
return "Parent{" +
"name='" + name + ''' +
", child=" + child +
'}';
}
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
class Child implements Cloneable {
private String name;
public Child(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Child{" +
"name='" + name + ''' +
'}';
}
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
2) 测试
@Test
public void testWeakClone() {
Child child = new Child("child");
Parent parent = new Parent("parent", child);
Parent parentClone = (Parent) parent.clone();
parentClone.getChild().setName("childClone");
System.out.println(parent);
System.out.println(parentClone);
}
3) 结果
Parent {name='parent', child=Child{name='childClone'}}
Parent {name='parent', child=Child{name='childClone'}}
2.深克隆
1) Parent与Child类
public class Parent implements Cloneable, Serializable {
private String name;
private Child child;
public Parent(String name, Child child) {
this.name = name;
this.child = child;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
@Override
public String toString() {
return "Parent{" +
"name='" + name + ''' +
", child=" + child +
'}';
}
// 深克隆 - 方式1 使用clone方法
@Override
protected Object clone() {
try {
Parent parentClone = (Parent) super.clone();
// 引用类型克隆
parentClone.child = (Child) this.child.clone();
return parentClone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
// 深克隆 - 方式2 通过对象的序列化实现(推荐)
public Object deepClone() {
// 创建流对象
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);
Parent parentClone = (Parent)ois.readObject();
return parentClone;
} catch (Exception e) {
return null;
} finally {
// 关闭流
try {
ois.close();
bis.close();
oos.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Child implements Cloneable, Serializable {
private String name;
public Child(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Child{" +
"name='" + name + ''' +
'}';
}
@Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
2) 测试
@Test
public void testDeepClone1() {
Child child = new Child("child");
Parent parent = new Parent("parent", child);
Parent parentClone = (Parent) parent.clone();
parentClone.getChild().setName("childClone");
System.out.println(parent);
System.out.println(parentClone);
}
@Test
public void testDeepClone2() {
Child child = new Child("child");
Parent parent = new Parent("parent", child);
Parent parentClone = (Parent) parent.deepClone();
parentClone.getChild().setName("childClone");
System.out.println(parent);
System.out.println(parentClone);
}
3) 结果
Parent {name='parent', child=Child{name='child'}}
Parent {name='parent', child=Child{name='childClone'}}
四、浅克隆与深克隆
1.浅克隆
1) 对于数据类型是基本数据类型的成员变量,浅克隆会直接进行值传递,也就是将该属性值复制一份给新的对象
2) 对于数据类型是引用数据类型的变量,那么浅克隆会进行引用传递,只是将成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。
3) 浅克隆是使用默认的clone()方法来实现
2.深克隆
1) 复制对象的所有基本类型的成员变量
2) 为所有引用数据类型的成员变量申请存储空间,并复制每个引用类型成员变量所引用的对象,直到该对象可达的所有对象
3) 深克隆实现方式1:重写clone方法来实现深克隆
4) 深克隆实现方式2:通过对象序列化实现深克隆(推荐)