原型模式(创建型模式)深复制与浅复制区别

定义

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

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

通俗的来说:对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。

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

通俗的来说:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。

 

如果不知道值类型和引用类型有什么不同,可以通过这两个链接了解

https://blog.csdn.net/liangjiabao5555/article/details/86552397

https://blog.csdn.net/liangjiabao5555/article/details/86559304

 

类图

 实例:浅复制

 

工作经历类

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 SetParsonalInfo(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.SetParsonalInfo("男", "29");
        a.SetWorkExperience("1998-2000", "XX公司");

        Resume b = (Resume)a.Clone();
        b.SetWorkExperience("1998-2006", "YY公司");

        Resume c = (Resume)a.Clone();
        c.SetParsonalInfo("女", "24");
        c.SetWorkExperience("1998-2003", "ZZ公司");

        a.Display();
        b.Display();
        c.Display();
        new Resume("大鸟");
        Console.Read();
    }

结果显示

为什么浅复制改变c的Age值为24,a、b的Age没有变。但改变c的工作经历,a、b的工作经历却跟着变?

 

实例:深复制

 

工作经历

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 SetParsonalInfo(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;
        }
    }

客户端代码一样

 

显示结果

为什么深复制中a、b、c的值互相不影响?

 

浅复制与深复制区别详解

讲到它们之间的区别就要知道实例化对象在堆和栈中时如何存在的,详解查看链接

https://blog.csdn.net/liangjiabao5555/article/details/87551343

 

浅复制

由于浅复制引用类型只复制引用,不复制引用的对象,所以当引用对象改变之后,其余引用的变量显示的结果都会改变。Name、Sex、Age都是Resume(简历)类的自带属性,而工作时间和工作公司在WorkExperience(工作经历)类中,当在Resume类使用WorkExperience类的实例化对象work时,这是引用类型,引用work对象里的属性。

Name、Sex、Age都复制了新的引用对象,work是复制了引用,即复制了workDate、Company的引用,所以更改c对象的Sex、Age时不会改变a、b的,而改变workDate、Company,他们引用的都是同一对象,a、b都会一起改变。

视图详解

由于时间问题,图中只画了a、b两个对象,但足以看出复制完的结果,经过复制,Resume对象变成了两个,而引用的workExperience对象还是一个

 

深复制

       private Resume(WorkExperience work)
        {
            //提供Clone方法调用的私有构造函数,以便克隆“工作经历”的数据
            this.work = (WorkExperience)work.Clone();

        }

通过Resume类中的这段代码可以知道深复制里最重要的,就是在Resume类里将workExperience对象进行了复制。为了避免多个Resume对象引用同一个workExperience对象。所以每当实例化Resume一个对象时,同时也创建一个新的workExperience对象,相当于一个深复制进行了两次复制。一次复制workExperience对象,一次复制Resume对象。

视图详解

这样无论更改a、b谁的值,都不会对其他对象造成影响。

以上便是原型模式的详细解释

 

注释:视图中Resume属性Work应先指向栈中workExperience的实例化声明的work,然后work再指向堆中workExperience的对象具体数据,由于为了图片更简单直白,所以没有画,望谅解。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章