自从克隆羊多莉但是后,Clone这个词就流行了起来。
在设计模式中,也有一种Clone的技术——原型模式,可以实现对象的克隆。
原型模式用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型类代码:
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。
在客户端克隆时代码:
在C#里面,我们可以很容易的通过Clone()方法实现原型模式。任何类,只要想支持克隆,必须实现C#中的ICloneable接口。ICloneable接口中有一Clone方法,可以在类中复写实现自动以的克隆方法。克隆的实现方法有两种:深复制与浅复制。
浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。
例如:细胞的复制过程:
namespace 细胞克隆1
{
class Cell : ICloneable
{
private string name;
private string color;
public string Name
{
set { name = value; }
get { return name; }
}
public string Color
{
set { color = value; }
get { return color ; }
}
public Cell(string name, string color)
{
this.name = name;
this.color = color;
Console.WriteLine("{0}的颜色是:{1}", name, color);
}
public object Clone() //实现ICloneable的Clone方法,用来克隆对象
{
return (object)this.MemberwiseClone();
}
}
class Program
{
static void Main(string[] args)
{
Cell cellOne = new Cell("cellOne", "red");
Cell cellTwo = (Cell)cellOne.Clone();
Console.WriteLine("cellTwo的名字是:{0},颜色是:{1}", cellTwo.Name, cellTwo.Color);
}
}
}
运行结果:
可以看出,再克隆cellTwo时,并没有调用Cell的构造函数,但是却将CellOne的字段执行逐位复制,然后给cellTwo.
一般我们在构造对象的时候,每NEW一次,就需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行这个初始化操作就太低级了。
一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高。它等于是不用重新初始化对象,而是动态地获得对象运行时的状态。
深复制:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。
对上述程序做些改动,在其中加入了一个细胞核的类,并在细胞类的声明中定义了细胞核作为数据成员,那么,在克隆的时候,参考:
MemberwiseClone()方法作用:如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一个对象。
所以,如果要让细胞核类也同时和字段复制过去的话,就要重新改写Clone函数了。
代码如下:
namespace 细胞克隆1
{
class Nucleus : ICloneable //定义细胞核类
{
private string size;
public string Size
{
set { size = value; }
get { return size; }
}
public object Clone() //实现ICloneable的Clone方法,用来克隆对象
{
return (object)this.MemberwiseClone();
}
}
class Cell : ICloneable
{
private string name;
private string color;
private Nucleus nucleus; //定义细胞核
public string Name
{
set { name = value; }
get { return name; }
}
public string Color
{
set { color = value; }
get { return color ; }
}
public Cell(string name, string color)
{
this.name = name;
this.color = color;
nucleus = new Nucleus();
Console.WriteLine("{0}的颜色是:{1}", name, color);
}
private Cell(Nucleus nucleus)
{
this.nucleus = (Nucleus)nucleus.Clone(); //提供clone方法调用的私有构造函数,以便克隆细胞核
}
public void SetNucleusSize(string size)
{
nucleus.Size = size;
}
public string ShowNucleusSize()
{
if(nucleus!=null)
return nucleus.Size;
return "0";
}
//调用私有的构造方法,让细胞核克隆完成,然后再给细胞的其它字段依次赋值,然后返回一个深复制的对象。
public object Clone()
{
Cell cell = new Cell(this.nucleus);
cell.Name = this.Name;
cell.Color = this.Color;
return cell;
}
}
class Program
{
static void Main(string[] args)
{
Cell cellOne = new Cell("cellOne", "red");
cellOne.SetNucleusSize("100");
Cell cellTwo = (Cell)cellOne.Clone();
Console.Write("cellTwo的名字是:"+cellTwo.Name+" 颜色是:"+cellTwo.Color);
Console.WriteLine (" 细胞核大小为:"+cellTwo.ShowNucleusSize());
}
}
}
可以看出,此时CellTwo,不仅将字段复制过去了,而且,Nucleus的内容也复制过去了。
原文:http://blog.csdn.net/lhc1105/article/details/21159603