原型模式-2

来源:互联网 发布:手工客软件 编辑:程序博客网 时间:2024/05/29 18:44
原型模式的核心是一个clone方法,通过这个方法进行对象的复制,在java中,提供了一个Cloneable接口来标示这个对象是可复制的,在本例中DayLife对象就实现了Cloneable接口。为什么说是“标示”呢?查看Clonealbe类源码,会发现,Cloneable接口中一个方法都没有,这个接口的作用就是一个标示,只有实现该接口的对象才有可能被复制!如何从“有可能被复制”变成“可以被复制”呢,方法就是覆盖超类Object的clone()方法!
1.克隆对象时对象的构造方法不执行,这个我们已经在原型模式-1中测试过了。
2.这里我们主要测试另外一个问题:浅复制和深复制

创建一个Model类,该类实现Cloneable接口。

package com.demo.prototype.clonetest;import java.util.ArrayList;public class Model implements Cloneable {private String te = ""; private ArrayList<String> nameList= new ArrayList<String>(); public ArrayList<String> getNameList() {return nameList;}public String getTe() {return te;}public void putTe(String str) { te = str;}//添加内容public void add(String str){this.nameList.add(str);}//Clone方法@SuppressWarnings("unchecked")@Overridepublic Model clone(){try {Model model = (Model)super.clone();return model;} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}}

创建一个测试类:

package com.demo.prototype.clonetest;public class TestMain {public static void main(String args[]){//创建modle对象Model model = new Model();//设置model对象内容model.add("aa");model.add("bb");model.putTe("abc123");//打印显示model中namelist内容System.out.println(model.getNameList());System.out.println(model.getTe());//将model内容克隆给model2Model model2 = model.clone();model2.add("cc");model2.putTe("def456");//打印显示model2中namelist内容System.out.println(model2.getNameList());System.out.println(model2.getTe());//打印显示model中namelist内容System.out.println(model.getNameList());System.out.println(model.getTe());}}
测试结果:

[aa, bb]abc123[aa, bb, cc]def456[aa, bb, cc]abc123

发现model的内容发生变化了,再仔细观察是nameList发生变化了。

这说明对克隆对象的修改,影响了原始对象的内容!这可不是我们想看到的结果!这就是浅复制所带来的
结果。
(1)浅复制
Object类的clone方法只是复制本对象的原始数据类型,如int,float、String等,对于数组和对象引用
等是不会复制的。因此,浅复制是有风险的。如何才能完全克隆呢?这就需要深复制了。
(2)深复制
深复制是指对于对象中的数组和对象引用也做复制的行为,从而达到将对象完全复制的效果。
例如,可将上面例子中Model的Clone()方法进行修改,如下:

package com.demo.prototype.clonetest;import java.util.ArrayList;public class Model implements Cloneable {private String te = ""; private ArrayList<String> nameList= new ArrayList<String>(); public ArrayList<String> getNameList() {return nameList;}public String getTe() {return te;}public void putTe(String str) { te = str;}//添加内容public void add(String str){this.nameList.add(str);}//Clone方法@SuppressWarnings("unchecked")@Overridepublic Model clone(){try {Model model = (Model)super.clone();model.nameList = (ArrayList<String>) this.nameList.clone();//对数组进行复制return model;} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}}

测试结果:

[aa, bb]abc123[aa, bb, cc]def456[aa, bb]abc123

看,说明model和它的复制对象model2已经没有联系了。

从以上内容可以看到,Object的clone方法只是做浅复制,也就是直接复制类的字段内容,并不管属性字段对象的内容,我们可以在重载的clone方法中进行类的“深复制”,从而到达完全克隆的目的。

0 0
原创粉丝点击