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

设计模式这本书通过对小菜求职复印简历,给我们引出了原型模式:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。其实说简单点就是我们创建好一个模板,然后进行复制,或者将模板修改后进行制……

由于MemberwiseClone()方法对于字段为值类型的,则对该字段执行逐位复制;如果字段是引用类型,则复制引用但不复制引用的对象,因此原始对象及其复本引用同一对象。所以我们把复制分为浅复制和深复制!

浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而其所有的对其他对象的引用都仍然指向原来的对象。

解释:一个对象中的字段有的是值类型的,有的是引用类型的。对于值类型字段来说,它的值就是简单的值,而对于引用类型来说,它的值是地址。浅复制在复制时,就是将这个对象的值字段和引用字段全部复制过去,、获得了这个对象的值和地址。所以当一个对象的引用字段所指向的地址中的变量变化时,所有浅复制对象中的该引用字段都会发生变化。

<span style="font-size:18px;">class Program
    {
        //工作经历
        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();
            }
            static void Main(string[] args)
            {
                Resume a = new Resume("大鸟");
                a.SetPersonalInfo("男", "29");
                a.SetWorkExperience("1998-2000", "xx公司");

                Resume b = (Resume)a.Clone();
                b.SetWorkExperience("1998-2006", "yy企业");

                Resume c = (Resume)a.Clone();
                c.SetPersonalInfo("男", "24");
                c.SetWorkExperience("1998-2003", "zz企业");

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

                Console.Read();
            }
        }
</span>

我们在“简历”类中设计了一个“设置工作经历”的方法,然后又设计了一个“工作经历”的类,“简历”类直接调用“工作经历”类中的对象。由于这是引用类型,当b和c克隆于a时只是复制了引用,对引用的对象还是指向了原来的对象,所以结果是看到三个引用都是最后一次的设置,因为三个引用都指向了同一个对象。就是a中的引用类型的内容没有复制给b和c,所以b和c都要指向a中的那个部分。

深复制:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

解释:被复制对象会将所有非引用类型的字段复制给新对象,同时将引用类型指向地址中存的对象复制给新对象。

<span style="font-size:18px;">class Program
    {
        //工作经历
        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();
            }
            static void Main(string[] args)
            {
                Resume a = new Resume("大鸟");
                a.SetPersonalInfo("男", "29");
                a.SetWorkExperience("1998-2000", "xx公司");

                Resume b = (Resume)a.Clone();
                b.SetWorkExperience("1998-2006", "yy企业");

                Resume c = (Resume)a.Clone();
                c.SetPersonalInfo("男", "24");
                c.SetWorkExperience("1998-2003", "zz企业");

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

                Console.Read();
            }
        }
</span>

“简历“和”工作经历“两个类都要实现克隆接口,在”简历“类中引用一个”工作经历“对象work,然后在”简历“实现克隆方法时调用私有的构造函数,让”工作经历“克隆完成,再进行对象的相关字段赋值。说白了深复制就是”简历“先把”工作经历“中的东西复制过来,所以a中的“工作经历”就不是引用类型,所以在复制给b和c的时候可以直接给复制过去。然后再对b和c进行赋值,就完成了深复制。

刚开始时,对深复制和浅复制很晕,后来和同学讨论后觉得应该这么理解……如果不对,还请大神来解救!

时间: 2024-12-07 08:56:35

原型模式——浅复制和深复制的相关文章

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

原型模式涉及一个浅复制和深复制的概念.原型模式可以简单理解为“复制”,但这个复制不是代码的复制.对同一个类,我们可以实例化new三次来“复制”,但如果在初始化的时候构造函数的执行很长,多次实例化就显得效率很低效了.那我们能否只实例化一次,然后“复制”呢? Test test1 = new Test(); Test test2 = test1; Test test3 = test1; 这样写吗?注意这是引用的复制,这实际上还是只有test1一个实例,test2.test3只是复制了其引用而已,如果

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

在学习设计模式中的原型模式中遇到了浅复制和深复制这两个陌生的面孔.它们到底是什么意思?浅和深到底是什么意思?还是需要来仔细研究一下的 首先,了解一下原型模式:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象.通俗的将其实就是复制. 若收到复制,并不陌生,但是怎么用,我们又该如何用才能达到更加灵活的复制呢? 浅复制: 1.首先要实现最简单的复制,我们用到的一个Clone的方法,具体用法如下: public override Prototype Clone() { return thi

也来谈一谈js的浅复制和深复制

1.浅复制VS深复制 本文中的复制也可以称为拷贝,在本文中认为复制和拷贝是相同的意思.另外,本文只讨论js中复杂数据类型的复制问题(Object,Array等),不讨论基本数据类型(null,undefined,string,number和boolean),这些类型的值本身就存储在栈内存中(string类型的实际值还是存储在堆内存中的,但是js把string当做基本类型来处理 ),不存在引用值的情况. 浅复制和深复制都可以实现在已有对象的基础上再生一份的作用,但是对象的实例是存储在堆内存中然后通

python基础之浅复制与深复制

关于列表.字典.元组的浅复制和深复制,数字和字符串没有浅复制和深复制一说.下面我直接用代码来体现: 1 import copy 2 3 names = ['Cahill','Teenglan','Eric','Peggie','Aalto','Baal','Sadie', 4 'Gage','Hagan','Jack','Kaley','Mabel','Lacy','Nadine','Pace','Amy'] 5 6 #浅复制 7 names2 = names.copy() 8 names2[1

JAVA浅复制与深复制

1.浅复制与深复制概念 ⑴浅复制(浅克隆)     多个变量指向一个对象    被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复制(深克隆)     每个变量指向一个对象,同时对象内包含对象,能复制内部对象    被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换言之,深复制把要复

转载:python中的copy模块(浅复制和深复制)

主要是介绍python中的copy模块. copy模块包括创建复合对象(包括列表.元组.字典和用户定义对象的实例)的深浅复制的函数. ########copy(x)########创建新的复合对象并通过引用复制x的成员来创建x的浅复制.更加深层次说,它复制了对象,但对于对象中的元素,依然使用引用.对于内置类型,此函数并不经常使用.而是使用诸如list(x), dict(x), set(x)等调用方式来创建x的浅复制,要知道像这样直接使用类型名显然比使用copy()快很多.但是它们达到的效果是一样

深度解析javascript中的浅复制和深复制

原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null,Undefined,Object五种类型.而Object又包含Function,Array和Object自身.前面的五种类型叫做基本类型,而Object是引用类型.可能有人就要问,为什么要分基本类型和引用类型呢?后面你就会明白的. 我们首先来看看浅复制和深复制的简洁定义: 深复制:直接将数据复制给

c++中浅复制与深复制

在C++中经常会遇到有关类对象的浅复制与深复制的问题,也是容易出错的地方. 查找了相关资料,有关浅复制与深复制的定义为:对类进行复制的时候按位复制,即把一个对象各数据成员的值原样复制到目标对象中.当类中涉及到指针类型数据成员的时候,往往就会产生指针悬挂问题. class A{ public: int* a; }; A a1; A b1=a1; b1=a1执行的是浅复制,此时a1.a和b1.a指向的是同一个内存地址,如果在析构函数里面有对内存的释放.就会出现内存访问异常.因为一块内存空间会被释放两

java基础-浅复制与深复制的理解

浅复制与深复制在很多编程语言中都有出现,那么什么是浅复制,什么是深复制呢? 要区分浅复制与深复制,首先我们要明确什么是复制,怎样才算是复制.复制的例子在生活中也随处可见,如复印一份文档,复制一段文字等.我们可以发现,复制操作后可以得到两份相同的东西,即复制由一变为二了.下面来看一个例子: public class User{ private int age; public int getAge(){ return age; } } User user1 = new User(); User us