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、相信自己。

    感谢您的宝贵时间~~~
  • 相关阅读:
    win10 uwp 弹起键盘不隐藏界面元素
    win10 uwp 存放网络图片到本地
    win10 uwp 存放网络图片到本地
    sublime Text 正则替换
    sublime Text 正则替换
    win10 uwp 绘图 Line 控件使用
    win10 uwp 绘图 Line 控件使用
    AJAX 是什么?
    什么是 PHP SimpleXML?
    PHP XML DOM:DOM 是什么?
  • 原文地址:https://www.cnblogs.com/zhoulitong/p/6412441.html
Copyright © 2011-2022 走看看