介绍
是一种创建模式,用户通过一个对象,复制出一个内部属性一致的对象,通俗讲就是克隆,常用在创建复杂或构造耗时的实例中。复制一个已经存在的对象更加高效。
应用场景
- 类的初始化需要消耗大量的资源,可以通过原型拷贝规避;
- 通过new产生的对象需要非常繁琐的在准备和权限访问;
- 保护拷贝:同一个对象可能需要多个调用者修改其中的属性,原型模式可以拷贝多个副本提供使用;
UML
UML.png上代码
- 浅拷贝
public class WordDocument implements Cloneable {
private String mText;
private ArrayList<String> mImages = new ArrayList<>();
public WordDocument() {
System.out.println("----------------WordDocument构造-----------------");
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
public ArrayList<String> getmImages() {
return mImages;
}
public void setmImages(ArrayList<String> mImages) {
this.mImages = mImages;
}
public void addImage(String imageName) {
mImages.add(imageName);
}
@Override
public String toString() {
return "WordDocument{" +
"mText='" + mText + '\'' +
", mImages=" + mImages +
'}';
}
}
测试
private static WordDocument documentClone;
public static void main(String[] args) {
WordDocument document = new WordDocument();
document.setmText("Document");
document.addImage("image1.jpg");
document.addImage("image2.jpg");
document.addImage("image3.jpg");
System.out.println(document);
try {
documentClone = (WordDocument) document.clone();
System.out.println(documentClone);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
document.setmText("update");
document.addImage("image4");
System.out.println(document.getmImages() == documentClone.getmImages());
System.out.println(document.getmText() == documentClone.getmText());
System.out.println();
}
输出结果
浅拷贝.png注释:
- 修改了mText,克隆对象没有变,而ArrayList却是相同的对象,为什么呢?因为Java克隆,基础类型克隆的是值,引用类型克隆的是引用。
string,integer是线程安全的不可变类,每一次赋值,指向的都是堆上的一个新的对象,所以这里导致了上面的结果。
为了解决上述问题,原型模式提出了
- 深拷贝
修改clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
WordDocument document = (WordDocument) super.clone();
document.mText = this.mText;
document.mImages = (ArrayList<String>) this.mImages.clone();
return document;
}
输出
深拷贝.png- 深拷贝和浅拷贝的区别就在于clone 方法,
注意
- 通过拷贝的对象不会执行构造函数,
- clone是Object的方法并不是Cloneable中的方法,但是想要实现clone必须实现Cloneable,不然会有CloneNotSupportedException异常
网友评论