大话设计模式,让你的代码更完美5---浅复制和深复制

来源:互联网 发布:淘宝网夏装新款女装 编辑:程序博客网 时间:2024/06/05 06:10

当前存在一个对象“张三”,由于需求导致需要我们创建一个类似的对象“李四”,这两个对象都属于Person类,按照以往我们都会通过new的方式去创建“李四”,

但是这样新创建的对象必然会走构造函数,这样会给系统增加诸多开支,降低效率,这时候我们就需要克隆(Clone)。

克隆就是从一个对象创建另外一个可定制的对象,而不需要知道任何创建的细节,不走构造函数等等。

在C#语言中提供了ICloneable接口,实现该接口即实现该接口的Clone方法,该方法的内容一般为下:

        public Object Clone()        {            return (Object)this.MemberwiseClone();        }

在这里要说一点,克隆一般用在初始化信息不发生改变的情况下使用的,这可以隐藏部分细节,提高性能。

MemberwiseClone()方法是浅复制方法:

所谓浅复制方法,即将A对象中的值类型依次复制,A对象中的引用对象只复制其地址,不复制其引用的对象。

例如:

简历对象:

    //简历    class Resume : ICloneable    {        private string name;        private string sex;        private string age;        private WorkExperience work;        public Resume(string name)        {            this.name = name;            work = new WorkExperience();        }        //设置个人信息        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()        {            return (Object)this.MemberwiseClone();        }    }


工作经历对象:

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

主函数:

        static void Main(string[] args)        {            Resume a = new Resume("大鸟");            a.SetPersonalInfo("男", "29");            a.SetWorkExperience("1998-2000", "XX公司");            a.Display();            Resume b = (Resume)a.Clone();            b.SetPersonalInfo("女", "123");            b.SetWorkExperience("1998-2006", "YY企业");            a.Display();            b.Display();            Console.Read();        }


在上述例子中,我们创建了一个简历a并设置相关参数,然后对其进行克隆,克隆出来为b

然后通过setPersonalInfo修改了b的姓名和年龄,再通过SetWorkExperience方法去修改其的工作时间和企业名,

最后输出a和b的详细简历。

输出结果如下:


我们发现非引用类型修改后会直接改变其值,a和b之间该部分自个为体,互不干扰

引用类型改变后,所有的克隆对象都会受改变,因为b和a共用一个引用对象(地址),即b将引用对象的值改变了,a也受影响。


深复制:b将a对象中的引用对象也复制过来,不再引用a原有被引用的对象。

深复制代码相比浅复制代码,主要有以下修改:

Resume类中添加了私有构造:

        private Resume(WorkExperience work)        {            this.work = (WorkExperience)work.Clone();        }

Resume类中修改了克隆方法:

        public Object Clone()        {            Resume obj = new Resume(this.work);            obj.name = this.name;            obj.sex = this.sex;            obj.age = this.age;            return obj;        }


WorkExperience类实现了ICloneable接口,实现了Clone方法:

        public Object Clone()        {            return (Object)this.MemberwiseClone();        }

主函数代码:

        static void Main(string[] args)        {            Resume a = new Resume("大鸟");            a.SetPersonalInfo("男", "29");            a.SetWorkExperience("1998-2000", "XX公司");            Resume b = (Resume)a.Clone();            b.SetPersonalInfo("女", "123");            b.SetWorkExperience("1998-2006", "YY企业");            a.Display();            b.Display();            Console.Read();        }

运行结果:



代码解析:

浅克隆无法让b对象克隆a对象中的对象,那么深克隆应该怎么做呢?自已想一下那不就是让a对象中的对象也实现ICloneable接口就好了?

1.让WorkExperience(工作经历)实现ICloneable接口,可以实现对其的克隆。

2.在Resume中创建克隆该对象中的引用对象的方法(Clone),Clone方法中通过私有构造获取当前对象中引用对象的克隆对象,然后将其相关参数赋值给一个新对象.

3.当代码走完Resume obj = new Resume(this.work);这句话时,obj是null,并不是有值的,接下来的赋值才知给予其内容,这个方法走完才是克隆完成。

4.联想与扩展,这个时候可以想一下dataset中得clone和copy,clone支付制结构,copy赋值结构和内容,就实现了深复制。


0 0
原创粉丝点击