在设计模式中的prototype模式中,要特别留意的是其中的深复制和浅复制,现在小结一下
1 浅复制
当进行浅复制时,如果类中包含了子对象,当这个类的包含的子引用对象发生改变时,这个变化会同时出现在它的浅复制克隆的对象中
去,比如
public class Lay1 implements Cloneable {
public int x;
public Lay2 lay2;
public Object clone()
{
Object clone=null;
try
{
clone=super.clone();
}
catch (CloneNotSupportedException e)
{
}
return clone;
}
}
Lay1中包含子对象lay2了,lay2指向一个类Lay2
public class Lay2 implements Cloneable {
public int y;
public Object clone()
{
Object clone=null;
try
{
clone=super.clone();
}
catch (CloneNotSupportedException e)
{
}
return clone;
}
}
客户程序
public class Client {
public static void main(String argv[])
{
Lay1 obj1=new Lay1();
obj1.lay2=new Lay2();
obj1.x=1;
obj1.lay2.y=1;
Lay1 obj2=(Lay1)obj1.clone();
obj2.x=2;
obj2.lay2.y=2;
System.out.println("obj1.x is:"+obj1.x+"/tObj1.lay2.y is:"+obj1.lay2.y);
System.out.println("obj2.x is:"+obj2.x+"/tObj2.lay2.y is:"+obj2.lay2.y);
}
}
输出为
obj1.x i s:1 obj1.lay2.y=2
obj2.x is 2 obj2.lay2.y=
可以看到 obj1当前层的对象别clone了一份,但clone对象的值的改变不反映到父对象,但修改其引用的子对象lay2的值,会反映到父方,因为大家都是指向同一个地方嘛。
为了深复制,可以这样做
public class Lay1 implements Cloneable {
public int x;
public Lay2 lay2;
public Object clone() {
Lay1 temp=null;
try {
temp=(Lay1)super.clone();
temp.lay2=(Lay2)lay2.clone();
}
catch (CloneNotSupportedException e) {
// should never happen
}
return temp;
}
}
public class Lay2 implements Cloneable {
public int y;
public Object clone() {
Object clone = null;
try {
clone = super.clone ();
}
catch (CloneNotSupportedException e) {
// should never happen
}
return clone;
}
}
public class Client {
public static void main(String argv[])
{
Lay1 obj1=new Lay1();
obj1.lay2=new Lay2();
obj1.x=1;
obj1.lay2.y=1;
Lay1 obj2=(Lay1)obj1.clone();
obj2.x=2;
obj2.lay2.y=2;
System.out.println("obj1.x is:"+obj1.x+"/tObj1.lay2.y is:"+obj1.lay2.y);
System.out.println("obj2.x is:"+obj2.x+"/tObj2.lay2.y is:"+obj2.lay2.y);
}
可以看到。输出是
obj1.x is:1 Obj1.lay2.y is:1
obj2.x is:2 Obj2.lay2.y is:2
另外,给出C#版本的代码,注意C#中浅复制用到的memberwiseclone()(转自
http://www.cnblogs.com/zhenyulu/articles/39257.aspx)
using System;
class ShallowCopy : ICloneable
{
public int[] v = {1,2,3};
public Object Clone()
{
return this.MemberwiseClone();
}
public void Display()
{
foreach(int i in v)
Console.Write( i + ", ");
Console.WriteLine();
}
}
class Client
{
public static void Main()
{
ShallowCopy sc1 = new ShallowCopy();
ShallowCopy sc2 = (ShallowCopy)sc1.Clone();
sc1.v[0] = 9;
sc1.Display();
sc2.Display();
}
}
ShallowCopy对象实现了一个浅拷贝,因此当对sc1进行克隆时,其字段v并没有克隆,这导致sc1与sc2的字段v都指向了同一个v,因此,当修改了sc1的v[0]后,sc2的v[0]也发生了变化。
深复制
using System;
class DeepCopy : ICloneable
{
public int[] v = {1,2,3};
// 默认构造函数
public DeepCopy()
{
}
// 供Clone方法调用的私有构造函数
private DeepCopy(int[] v)
{
this.v = (int[])v.Clone();
}
public Object Clone()
{
// 构造一个新的DeepCopy对象,构造参数为
// 原有对象中使用的 v
return new DeepCopy(this.v);
}
public void Display()
{
foreach(int i in v)
Console.Write( i + ", ");
Console.WriteLine();
}
}
class Client
{
public static void Main()
{
DeepCopy dc1 = new DeepCopy();
DeepCopy dc2 = (DeepCopy)dc1.Clone();
dc1.v[0] = 9;
dc1.Display();
dc2.Display();
}
}
这次在克隆的时候,不但克隆对象本身,连里面的数组字段一并克隆。因此,最终打印出来的dc1与dc2不同。