zoukankan      html  css  js  c++  java
  • 设计模式——浅复制VS深复制

    背景

       在学习原型模式的时候,采用了一个区别与其他模式的新方法。采用了“克隆(Clone)方法。通过实现ICloneable接口中的Clone()方法来达到克隆的目的。代码实现过程中,存在了我们所说的浅复制和深复制,下面看看有什么区别。

    内容

    代码实现

    简历浅复制实现:

    <span style="font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:24px;">using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 浅复制
    {
        class Program
        {
            static void Main(string[] args)
            {
                Resume a = new Resume("大鸟");
                a.SetPersonalInfo("男", "29");
                a.SetWorkExperience("1992-2002", "XX公司");
    
                Resume b = (Resume)a.Clone();
                b.SetWorkExperience ("1992-2002","YY公司");
    
                Resume c=(Resume )a.Clone ();
                c.SetPersonalInfo ("男","24");
                c.SetWorkExperience ("1995-2200","ZZ企业");
    
                a.Display ();
                b.Display ();
                c.Display ();
                Console .Read ();
            }
        }
        //工作经历类
        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; }
    
            }
    
        }
    
        //简历类
        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();
            }
        }
    }
    </span></span>
    结果为:
               

    简历深复制实现:

    <span style="font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:24px;">//作者:周丽同
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 简历的深复制实现
    {
        class Program
        {
            static void Main(string[] args)
            {
                Resume a = new Resume("大鸟");
                a.SetPersonalInfo("男", "29");
                a.SetWorkeExperience("1998-2000", "XX公司");
    
                Resume b = (Resume)a.Clone();
                b.SetWorkeExperience("1998-2006", "YY公司");
    
                Resume c = (Resume)a.Clone();
                c.SetPersonalInfo("男", "24");
                c.SetWorkeExperience("1998-2003", "ZZ企业");
    
                a.Display();
                b.Display();
                c.Display();
    
                Console.Read();
            }
        }
    
        //改动的地方是:让工作经历也实现ICloneable接口
        //工作经历类
        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 (Object)this.MemberwiseClone();//“工作经历”类实现克隆方法;
            }
        }
    
        //简历类
        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();
            }
            private Resume (WorkExperience work)
            {   
                //提供克隆(Clone)方法调用的私有构造函数,以便克隆“工作经历”的数据;
                this.work = (WorkExperience)work.Clone();
    
            }
    
            //设置个人信息
            public void SetPersonalInfo(string sex,string age )
            {
                this.sex = sex;
                this.age = age;
            }
            //设置工作经历
    
            public void SetWorkeExperience(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;
            }
        }
    
    }</span></span>

    结果是:                                   

                                              

       从上面的例子可以看出为什么对于值类型的对象,在克隆的时候可以轻易的复制过来,但是对于引用类型的,在克隆的时候复制过来的只是引用对象,而引用对象的数据是不会复制过来的。这里涉及到了什么是值类型和引用类型,它们在内存中是怎么“走的”。且看且分析:

     

    值类型

    引用类型

    类型

    结构体;数值类型(整型);浮点型;decimal型;bool型;枚举;可空类型;

    数组;用户定义的类;接口;委托; Object类型;字符串类型;

    是否可以包含null值

    内存分配

    分配在栈中

    分配在堆中

    主要职责

    存储数据

    传递引用(相当于指针)

    适用场合

    该类型的共有接口完全由一些数据成员存取属性定义;

    永远不可能又子类;

    不具有多态行为;

    具有多态行为;

    用于定义应用程序的行为;

    浅复制和深复制含义

       在这里如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型的,则复制引用但不复制引用的对象。对于浅复制和深复制从下面的图来看:

    浅复制:

                                                                                                       

    深复制:

                                                                                                     

       通过上面的图和代码我们可以知道,可以根据我们的需要进行深复制和浅复制。当需要深复制的时候就需要加上一段对引用对象的深复制(克隆)。我理解深复制,在内存中的走向是: 

    小结

       以上是本人关于c#中浅复制和深复制的一些理解,自己的理解还是有点表面,多多实践例子就会好很多,望各路大神提出宝贵意见。
    1、不要害怕自己的想法不对,对不对试试就知道了。
    2、学会站在巨人的肩膀上。
    3、相信自己。

    感谢您的宝贵时间~~~
  • 相关阅读:
    git 的学习使用记录
    Servlet发送邮件遇到的问题SMTPSendFailedException 554
    如何高效地写CSS--等以后有空多加总结一下
    前端技术科技树梳理
    React了解
    读取Excel文件
    Eclipse不能自动编译 java文件
    破天荒地敲下第一篇
    SRM DIV2 569 TheDeviceDiv2
    SRM DIV2 570 RobotHerbDiv2
  • 原文地址:https://www.cnblogs.com/zhoulitong/p/6412441.html
Copyright © 2011-2022 走看看