设计模式 原型模式
1.设计模式背景
在某些场景下,我们需要拷贝对象,普通设计方式会直接new一个新的对象,然后setter各种属性。缺点是:这种方式太麻烦。
这时候就可以使用到原型模式,通过Object的clone方法克隆对象,或者通过流。
2.使用方法
Object对象的clone方法,能够浅拷贝对象的primitive field,使用方式如下:
public class Person implements Cloneable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
3.如果存在引用型成员变量怎么办?
public class Person implements Cloneable{
private String name;
private int age;
private Department department;
经过测试发现,克隆对象中的department是同一个对象。
Person p1 = new Person();
p1.setDepartment(new Department("pA"));
Person clone = (Person)p1.clone();
System.out.println(clone.getDepartment() == p1.getDepartment());
3.1 在覆盖的clone方法中重新设置
@Override
protected Object clone() throws CloneNotSupportedException {
Person res = null;
res = (Person)super.clone();
Department dept = (Department)this.getDepartment().clone();
res.setDepartment(dept);
return res;
}
但是同样存在问题:如果引用型成员变量太多,也要一个个设置。
3.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);
Object o = ois.readObject();
return o;
} catch (Exception e) {
e.printStackTrace();
return null;
}
finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
test:
Person2 p2 = new Person2();
p2.setDepartment(new Department("abc"));
Person2 o = (Person2)p2.deepClone();
System.out.println(o);
System.out.println(p2);
System.out.println(o.getDepartment() == p2.getDepartment());
note : 利用序列化深拷贝的成员都要实现serilizable接口