记得有一次写程序,我需要做这样一件事,我需要对我当前的对象的所有内容做个保存,然后来操作它,并且还需要和原来的数据做对比。
这个对象大致如下:
public class A{
private String name;
private String id;
private ArrayList<String> image;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<String> getImage() {
return image;
}
public void setImage(ArrayList<String> image) {
this.image = image;
}
}
这好像是一件很简单的事,于是我就开始动手了,我先创建一个新的对象B,然后,用已有的对象A的所有字段来初始化B。
A b = new A();
b.setId(a.getId());
b.setName(a.getName());
b.setImage(a.getImage());
这样做完后,又有一个问题,这两个对象a,b都指向同一张图片,意味着它两永远是相同的,我怎么做对比。
好吧,我就卡这了。
经过我查资料,知道了,原来我完成的工作只是一个浅拷贝,而我想要的是深拷贝的结果,并且,我的代码写的非常差。这儿有个创建型的设计模式,叫做原型模式,可以很好地完成这个工作。
首先,浅拷贝:
public class A implements Cloneable{
private String name;
private String id;
private ArrayList<String> image;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<String> getImage() {
return image;
}
public void setImage(ArrayList<String> image) {
this.image = image;
}
@Override
protected Object clone() throws CloneNotSupportedException {
A aa = (A) super.clone();
aa.setName(this.getName());
aa.setId(this.getId());
aa.setImage(this.getImage());
return aa;
}
}
这是浅拷贝,和上面的代码差不多,但是,做到了封装,我们需要复制时,只需要调用方法即可,但是,在对比时,图片还是永远相同的。
我们来看看深拷贝:
public class A implements Cloneable{
private String name;
private String id;
private ArrayList<String> image;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<String> getImage() {
return image;
}
public void setImage(ArrayList<String> image) {
this.image = image;
}
@Override
protected Object clone() throws CloneNotSupportedException {
A aa = (A) super.clone();
aa.setName(this.getName());
aa.setId(this.getId());
aa.setImage((ArrayList<String>) this.getImage().clone());
return aa;
}
}
在这(ArrayList) this.getImage().clone(),调用了这个方法,就可以实现深拷贝,这样更加简单。
注意:创建对象是A aa = (A) super.clone();而不是通过new关键字来实现的。
有这样一句话,理解了就能正确的使用new 或supper.clone了:使用clone和new需要根据构造对象的成本来决定,如果对象的构造成本比较高或构造比较麻烦,那么使用clone函数效率比较高,否则可以使用new的形式。
以上复制一个对象的过程就是原型模式,我们要复制的对象就是原型。