首页 > 代码库 > 原型模式——浅复制VS深复制

原型模式——浅复制VS深复制

在学习设计模式中的原型模式中遇到了浅复制和深复制这两个陌生的面孔。它们到底是什么意思?浅和深到底是什么意思?还是需要来仔细研究一下的

        首先,了解一下原型模式:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。通俗的将其实就是复制。

            若收到复制,并不陌生,但是怎么用,我们又该如何用才能达到更加灵活的复制呢?

浅复制:

           1.首先要实现最简单的复制,我们用到的一个Clone的方法,具体用法如下:

public override Prototype Clone()

{

return this.MemberwiseClone(); //MemberwiseClone方法用来创建当前的浅表副本

}

           我们具体来看一下MemberwiseClone这个方法:创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果该字段是类型的,则对字段执行逐位复制,如果字段是引用类型的,则复制引用但不复制引用的对象

通过此方法可实现简单的原型复制。

      为什么只是说实现了简单的原型复制呢?难道还有更为复杂的吗?

       当我们在复制原型时,经常会遇到特殊变量不一致时,我们可以对变量进行重新赋值,达到数据不同的原型对象。那么此时,上述的这种办法还能满足我们的要求吗?

我们看到用红字标出来的部分,他告诉我们如果复制对象的字段是非值类型的,就能复制引用,不复制引用的对象。这句话到底是什么意思呢?

       根据我的理解:引用类型是需要另行分配空间的,只复制引用,不复制引用对象,就是对复制的对象不再另行分配空间,而是直接将复制引用数据直接写进为原来对象分配的空间中,这样其实造成的结果就是覆盖原来的数据。于是就出现了原型对象和克隆后的对象数据都只是最后一次被克隆时的数据。

那么怎么做,才能满足我们的要求呢?

深复制

     这就用到了我们题目中提到的深复制了。

我们来看一下简历制作具体的深复制的实现:

//工作简历类     class WorkExperience:ICloneable     {         private string workDate;         public  string WorkDate         {             get { return workDate; }             set { workDate = value; }         }         private string company;         public string Company         {             get { return company; }             set { company = value; }         }

        public Object Clone()         {             return this.MemberwiseClone(); //实现自身类(工作经历类)的浅表复制,由于此时简历中涉及到的数据位值类型,此时可复制自身对象的数据         }     }

 

    //简历类

    class Resume :ICloneable     {         private string name;         private string sex;         private string age;         private WorkExperience work; //此处引用工作经历类中的对象work         public Resume(string name)         {             this.name = name;             work = new WorkExperience(); //简历类实例化时,实例化工作经历类         }

        private Resume(WorkExperience work)         {             this.work = (WorkExperience )work.Clone(); //实现工作经历的数据复制         }

 

        //设置个人信息         public void SetPersonalInfo(string sex,string age)         {             this.sex = sex;             this.age = age;         }

 

        //设置工作经历         public void SetWorkExperience(string workDate,string company)         {             work.WorkDate =workDate ;             work.Company =company ;         }

 

        //显示         public void Display()         {             Console.WriteLine("{0} {1} {2}", name, sex, age);             Console.WriteLine("工作经历: {0} {1}", work.WorkDate, work.Company);         }

        public Object Clone()         {             Resume obj = new Resume(this.work); //通过私有构造方法,实现工作经历的数据复制, //再对象的其他字段赋值,便可事先深复制的简历 //对象

            //对其他参数进行赋值             obj.name = this.name;             obj.sex = this.sex;             obj.age = this.age;             return obj;

        }     }

客户端的代码如下:

static void Main(string[] args)         {             Resume a = new Resume("大鸟");             a.SetPersonalInfo("男", "29");             a.SetWorkExperience("1998-9-7", "XS"); //此时,我们用三组不同的数据进行检验

            Resume b= (Resume)a.Clone ();             b.SetWorkExperience ("1889-2-3","dfe");

            Resume c = (Resume)a.Clone();             c.SetPersonalInfo("女", "23");

            a.Display();             b.Display();             c.Display();

            Console.Read();         }

结果如下:


通过深复制,我们就可以实现相同简历不同数据的复制了。

那么,我们来分析一下,代码的具体含义,看看它是如何做到的。

1、们看代码可以知道,简历类与工作经历是一个组合关系。在面向对象语言中,聚合和组合关系通常要出现一个类来引用另一个类的对象或数据来实现二者之间的关联。

2、么我们只要在被引用的类(工作经历类)中利用Clone方法实现自身的浅表复制,此时由于被引用类中的类型为值类型(包括特殊的string类型)是可以实现自身数据的逐位复制的。那么接下来只要在引用类中调用被引用类中事先声明好的构造方法就可以最终事先工作经历的数据复制了。

3、通过引用类中的clone方法,调用被引用类中的构造方法事先工作经历的数据复制后,再对自身类(引用类)其他的字段进行赋值,最终事先深复制。

 

以上是我个人对原型模式中浅复制和深复制的理解!