1.拷贝对象
namespace Data
{
/// <summary>
/// 要被浅拷贝的对象
/// </summary>
public abstract class Prototype
{
public string ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public DegreeInfo DegreeInfo;
public Prototype(string id)
{
ID = id;
}
public void SetInfo(string name, string address)
{
Name = name;
Address = address;
}
/// <summary>
/// 返回本类的一个对象
/// </summary>
/// <returns></returns>
public abstract Prototype Clone();
}
public class PrototypeEx : Prototype
{
/// <summary>
/// 必须要有这个方法
/// </summary>
/// <param name="id"></param>
public PrototypeEx(string id)
: base(id)
{ }
/// <summary>
/// 创建一个对象的浅表副本。创建一个新对象,将当前对象的非静态字段复制到新对象。如果
/// 字段的类型是值类型,则对该字段进行逐位复制;若是引用类型,则复制引用,不复制对象。
/// 因此,原始对象和副本引用同一对象.
/// </summary>
/// <returns></returns>
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();//这里要强转
}
}
/// <summary>
/// 学历信息
/// </summary>
public class DegreeInfo
{
public string DegreeID { get; set; }
public string DegreeName;
public string University { get; set; }
public DegreeInfo(string id,string universityName)
{
DegreeID = id;
University = universityName;
}
}
/// <summary>
/// 要被拷贝的对象;进行深拷贝
/// </summary>
public class PrototypeExx : ICloneable
{
public string ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public DegreeInfoEx DegreeInfo;
public PrototypeExx()
{
}
public PrototypeExx(string id)
{
ID = id;
}
public void SetInfo(string name, string address)
{
Name = name;
Address = address;
}
/// <summary>
/// 进行一次深拷贝
/// </summary>
/// <returns></returns>
public object Clone()
{
PrototypeExx obj = new PrototypeExx();
obj.ID = this.ID;
obj.Name = this.Name;
obj.Address = Address;
obj.DegreeInfo = (DegreeInfoEx)this.DegreeInfo.Clone();
return obj;
}
}
/// <summary>
/// 学历信息;进行深拷贝
/// </summary>
public class DegreeInfoEx : ICloneable
{
public string DegreeID { get; set; }
public string DegreeName;
public string University { get; set; }
public DegreeInfoEx(string id, string universityName)
{
DegreeID = id;
University = universityName;
}
#region ICloneable 成员
public object Clone()
{
return (Object)this.MemberwiseClone();
}
#endregion
}
}
2.调用
static void Main(string[] args)
{
/*原型模式:使用MemberwiseClone方法对数据进行浅表拷贝;实现ICloneable接口进行深拷贝
* 从下面的实例看出:
* 1和2对比,当修改p1后,p2对应的数据没有变化,意味着p2是p1对象中非引用类型数据(包括string类型)的独立拷贝。
* 1和3对比,当修改p1中DegreeInfo类的信息后,p2的信息跟着变化,意味着p1,p2的DegreeInfo数据是引用的同一个对象
*
* 深拷贝能解决上面出现的问题,拷贝一份全新的对象
*
* 两种拷贝方式其实都是调用了同一个方法:MemberwiseClone。深拷贝不同之处在于实现了ICloneable接口。内部类的拷
* 贝还是属于浅拷贝
* */
Console.WriteLine("浅拷贝实例");
DegreeInfo info = new DegreeInfo("110344", "四川师范");
info.DegreeName = "本科";
PrototypeEx p1 = new PrototypeEx("344");
p1.SetInfo("yoyo1", "成都");
p1.DegreeInfo = info;
PrototypeEx p2 = (PrototypeEx)p1.Clone();
Console.WriteLine("1. {0},{1},{2},{3},{4},{5}",p2.ID,p2.Name,p2.Address,p2.DegreeInfo.DegreeID,p2.DegreeInfo.University,p2.DegreeInfo.DegreeName);
//修改p1对象信息
p1.SetInfo("yoyo3","北京");
Console.WriteLine("2. {0},{1},{2},{3},{4},{5}", p2.ID, p2.Name, p2.Address, p2.DegreeInfo.DegreeID, p2.DegreeInfo.University, p2.DegreeInfo.DegreeName);
//info.DegreeName = "专科";
p1.DegreeInfo.DegreeName = "专科";
Console.WriteLine("3. {0},{1},{2},{3},{4},{5}", p2.ID, p2.Name, p2.Address, p2.DegreeInfo.DegreeID, p2.DegreeInfo.University, p2.DegreeInfo.DegreeName);
Console.WriteLine("深拷贝实例");
DegreeInfoEx infoCQ = new DegreeInfoEx("110355", "重庆师范");
infoCQ.DegreeName = "本科";
PrototypeExx p3 = new PrototypeExx("355");
p3.SetInfo("yoyo2","重庆");
p3.DegreeInfo = infoCQ;
PrototypeExx p4 = (PrototypeExx)p3.Clone(); ;
Console.WriteLine("1. {0},{1},{2},{3},{4},{5}", p4.ID, p4.Name, p4.Address, p4.DegreeInfo.DegreeID, p4.DegreeInfo.University,p4.DegreeInfo.DegreeName);
p3.SetInfo("yoyo4", "昆明");
Console.WriteLine("2. {0},{1},{2},{3},{4},{5}", p4.ID, p4.Name, p4.Address, p4.DegreeInfo.DegreeID, p4.DegreeInfo.University, p4.DegreeInfo.DegreeName);
//修改p3
infoCQ.DegreeName = "专科";
Console.WriteLine("3. {0},{1},{2},{3},{4},{5}", p4.ID, p4.Name, p4.Address, p4.DegreeInfo.DegreeID, p4.DegreeInfo.University, p4.DegreeInfo.DegreeName);
Console.ReadKey();
}