小A:“克隆對象有哪些?”
大B:“克隆對象分爲淺拷貝和深拷貝。我給你詳細講一下。淺拷貝就是克隆的對象和它的源對象共享引用的對象,舉個例子,可能不恰當,假設牛肉刀削麪引用一個對象:Money,表示它值多少錢,這裡說的對象是說它是System.Object繼承的(c#),也就是說不同的淺拷貝對象,他們的價錢是一樣的,當克隆對象的價錢變過之後,它所引用的對象的價錢也就隨之改變了,比如麪館。調低了牛肉刀削麪的價格,由5塊錢調到了4塊錢,那麼每碗麪的價格都變到了4塊錢。但對值類型而言,每個淺拷貝對象都有自己的拷貝,也就是說,當改變克隆對象的值類型時,它的源對象相應屬性不會改變。深拷貝就是完全的拷貝。不僅值類型有自己的拷貝,連引用對象也有自己的一份拷貝,修改克隆對象的任何屬性,也不會對源對象產生任何影響。原型管理器,就是提供原型註冊使用,當創建對象使,可以使用裡面的對象進行克隆,當有新的實例對象時,也可以將他們加到原型管理器裡。說的有點亂,程序員,還是用代碼交流最好。”
下面的程序分別實現了原型克隆時淺拷貝和深拷貝。
//
//理解深拷貝和淺拷貝
//
//淺表副本創建與原始對象具有相同類型的新實例,然後複製原始對象的非靜態字段。
//如果字段是值類型的,則對該字段執行逐位複製。如果字段是引用類型,則複製該
//引用但不復制被引用的對象;這樣,原始對象中的引用和複本中的引用指向同一個對象。
//相反,對象的深層副本複製對象中字段直接或間接引用的全部內容。
//
//例如,如果X是一個具有對對象A和對象B的引用的Object,並且對象A還具
//有對對象M的引用,則X的淺表副本是對象Y,而Y同樣具有對對象A和對象。
//的引用。相反,X的深層副本是對象Y,而對象Y具有對對象C和對象D的直接引
//用以及對對象N的間接引用,其中C是A的副本,D是B的副本,而N是M的副本。
usingSystem;
usingSystem.Collections;
usingSystem.IO;
usingSystem.Runtime.Serialization.Formatters.Binary;
usingSystem.Runtime.Serialization;
usingSystem.Data;
namespacePrototype
{
///《summary》
///Prototype類型實例
///《/summary》
classTestPrototypeApp
{
///《summary》
///應用程序的主入口點。
///《/summary》
[STAThread]
staticvoidMain(string[]args)
{
//定義原型管理器
NoodleManagernoodleManager=newNoodleManager();
//客戶要求下面三碗麪
NoodlebeefNoodle=(Noodle)noodleManager[“牛肉拉麪”].Clone();
//NoodlebeefNoodle=(Noodle)noodleManager[“牛肉拉麪”].DeepClone();
NoodlemuttonNoodle=(Noodle)noodleManager[“羊肉拉麪”].Clone();
NoodlebeefCutNoodle=(Noodle)noodleManager[“牛肉刀削麪”].Clone();
//修改克隆對象中的引用對象的屬性,驗證它是淺拷貝還是深拷貝
beefNoodle.TbName=,“哈哈哈!克隆對象改名了,你改不改”;
//顯示原始對象的NoodelName和TbName?
Console.WriteLine(noodleManager[“牛肉拉麪”].NoodleName+noodleManager[“牛肉拉麪”].TbName+“\n”);
//顯示克隆對象的NoodleName和。
Console.WriteLine(beefNoodle.NoodleName+beefNoodle.TbName+“\n”);
//將新的產品加入原型管理器,以備以後克隆時使用,下面是定義了一種新的麪條-羊肉刀削麪,
//並把它添加到麪條管理器中,如果以後再有客戶點這個面,直接克隆即可。
noodleManager[“羊肉刀削麪”]=newCutNoodle(“羊肉刀削麪”);
//克隆一碗羊肉刀削麪
NoodlemuttonCutNoodle=(Noodle)noodleManager[“羊肉刀削麪”].Clone();
Console.WriteLine(noodleManager[“羊肉刀削麪”].NoodleName+“\n”);
Console.WriteLine(muttonCutNoodle.NoodleName+“\n”);
Console.ReadLine();
}
}
//抽象產品-麪條
//序列化屬性,爲深拷貝時使用,每個派生類都要加上此屬性才能實現深拷貝
[Serializable]
publicabstractclassNoodle
{
//定義一個DataTable對象,主要是爲了驗證對比類中含有引用對象時的深拷貝和淺拷貝時的不同,
//你也可以採用別的任何引用對象
protectedDataTabledataTable=newDataTable();
publicstringTbName
{
get{returndataTable.TableName;}
set{dataTable.TableName=value;}
}
//字段
protectedstringnoodleName;
//特性
publicstringNoodleName
{
get{returnnoodleName;}
set{noodleName=value;}
}
publicabstractNoodleMake(stringname);
//淺克隆的接口
publicabstractNoodleClone();
//深克隆的接口
publicabstractNoodleDeepClone();
}
//具體產品,拉麪
[Serializable]
publicclassPullNoodle:Noodle
{
publicPullNoodle(stringname)
{
this.NoodleName=name;
this.TbName=name+“table”;
Console.WriteLine(“PullNoodleismade\n”);
}
//實現淺拷貝
publicoverrideNoodleClone()
{
return(Noodle)this.MemberwiseClone();
}
//實現深拷貝,“淹鹹菜”的過程,先將對象序列化到內存流,再反序列化,即可得到深克隆
publicoverrideNoodleDeepClone()
{
//定義內存流
MemoryStreamms=newMemoryStream();
//定義二進制流
IFormatterbf=newBinaryFormatter();
//序列化
bf.Serialize(ms,this);
//重置指針到起始位置,以備反序列化
ms.Position=0;
//返回反序列化的深克隆對象
return(Noodle)bf.Deserialize(ms);
}
publicoverrideNoodleMake(stringname)
{
returnnewPullNoodle(name);
}
}
//具體產品-刀削麪
[Serializable]
publicclassCutNoodle:Noodle
{
publicCutNoodle(stringname)
{
this.NoodleName=name;
this.TbName=name+“table”;
Console.WriteLine(“CutNoodleismade\n”);
}
//實現淺克隆
publicoverrideNoodleClone()
{
return(Noodle)this.MemberwiseClone();
}
publicoverrideNoodleMake(stringname)
{
returnnewCutNoodle(name);
}
//實現深克隆
publicoverrideNoodleDeepClone()
{
MemoryStreamms=newMemoryStream();
IFormatterbf=newBinaryFormatter();
bf.Serialize(ms,this);
ms.Position=0;
return(Noodle)bf.Deserialize(ms);
}
}
//定義原型管理器,用於存儲原型集合,這裡採用的是。
classNoodleManager
{
//定義。
protectedHashtablenoodleHt=newHashtable();
protectedNoodlenoodle;
publicNoodleManager()
{
//初始化時加入三種基本原型
noodle=newPullNoodle(“牛肉拉麪”);
noodleHt.Add(“牛肉拉麪”,noodle);
noodle=newPullNoodle(“羊肉拉麪”);
noodleHt.Add(“羊肉拉麪”,noodle);
noodle=newCutNoodle(“牛肉刀削麪”);
noodleHt.Add(“牛肉刀削麪”,noodle);
}
//索引器,用於添加,訪問Noodle對象
publicNoodlethis[stringkey]
{
get{return(Noodle)noodleHt[key];}
set{noodleHt.Add(key,value);}
}
}
}