原型模式

原型模式就是从一个对象再创建另一个可定制的对象,而不需要知道任何创建的细节。

原型模式本身是比较简单的,不过其中牵涉到浅复制和深复制的实现,下面使用.Net自带的方法和接口分别实现浅复制和深复制:

    public class WorkExperience : ICloneable
    {
        public string workDate;
        public string experience;

        #region ICloneable 成员

        public object Clone()
        {
            //浅复制
            return this.MemberwiseClone();
        }

        #endregion
    }

  

MemberwiseClone方法实现的是浅复制,即如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象,因此,原是对象及其复本引用的是同一对象。不过,经过测试发现,对string类型的执行的复制与值类型是相同的,修改新变量中string的值不会影响原变量的值测试如下:

WorkExperience we = new WorkExperience();
we.workDate="today";
we.experience="test";
//输出为work experience: today, test Console.WriteLine("work experience: {0},{1}", we.workDate, e.experience); WorkExperience we2 = (WorkExperience)we.Clone(); we2.experience = "test2"; we2.workDate = "tomorrow";
//输出为work experience: tomorrow,test2 Console.WriteLine("work experience: {0},{1}", we2.workDate, e2.experience);
//输出为work experience: today, test
Console.WriteLine("work experience: {0},{1}", we.workDate, we.experience);

  

下面演示如何进行深复制和浅复制:

    public class Resume : ICloneable
    {
        public string name;
     //引用类型,需要区分深复制和浅复制 public WorkExperience workExperience; public Resume(string name) { this.name = name; workExperience = new WorkExperience(); } public void SetExperience(string workDate, string experience) { workExperience.workDate=workDate; workExperience.experience=experience; } public void Show() { Console.WriteLine("name : {0}",name); Console.WriteLine("work experience: {0},{1}",workExperience.workDate,workExperience.experience); } /// <summary> /// 提供一个私有构造函数,供复制方法使用,以便复制WorkExperience的数据 /// </summary> /// <param name="workExperience"></param> private Resume(WorkExperience workExperience) { this.workExperience = (WorkExperience)workExperience.Clone(); } #region ICloneable 成员 /// <summary> ///深复制,实例化一个新的对象 /// </summary> /// <returns></returns> public object Clone() { Resume newResume = new Resume(this.workExperience); newResume.name = this.name; return newResume; } /// <summary> /// 浅复制 /// </summary> /// <returns></returns> public object Copy() { return this.MemberwiseClone(); } #endregion }

 上例中Clone和Copy分别实现了深复制和浅复制,测试如下:

Resume myResume = new Resume("Kelly");
myResume.SetExperience("2004-2008", "University");
myResume.Show();


//使用浅复制,更改WorkExperience,则被复制对象也被更改
Resume newResume = (Resume)myResume.Copy();
newResume.SetExperience("2008-2012", "Master Degree");
newResume.name = "Mike";
myResume.Show();

//使用深复制,更改WorkExperience,被复制对象不会被更改
Resume newResume2 = (Resume)myResume.Clone();
newResume2.SetExperience("2012-now", "Company");
newResume2.name = "Jack";
myResume.Show();

  运行结果为:

name : Kelly
work experience: 2004-2008,University
name : Kelly
work experience: 2008-2012,Master Degree
name : Kelly
work experience: 2008-2012,Master Degree

可以看出,name由于是string类型,所以始终不会被修改,work experience是引用类型,在第一次做浅复制后被修改,第二次做深复制后没有被修改。

一般在初始化信息不发生变化的情况下,克隆是最好的办法,这即隐藏了对象创建的细节,又对性能有很大的提高。

原文地址:https://www.cnblogs.com/angela217/p/5405031.html