原型模式(創建型模式)深複製與淺複製區別

定義

原型模式:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象

淺複製:被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用都仍然只想原來的對象。

通俗的來說:對值類型的成員變量進行值的複製,對引用類型的成員變量只複製引用,不復制引用的對象。

深複製:把引用的變量指向複製的新對象,而不是原有的被引用的對象。

通俗的來說:對值類型的成員變量進行值的複製,對引用類型的成員變量也進行引用對象的複製。

 

如果不知道值類型和引用類型有什麼不同,可以通過這兩個鏈接瞭解

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的對象具體數據,由於爲了圖片更簡單直白,所以沒有畫,望諒解。

 

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