定義
原型模式:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象
淺複製:被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用都仍然只想原來的對象。
通俗的來說:對值類型的成員變量進行值的複製,對引用類型的成員變量只複製引用,不復制引用的對象。
深複製:把引用的變量指向複製的新對象,而不是原有的被引用的對象。
通俗的來說:對值類型的成員變量進行值的複製,對引用類型的成員變量也進行引用對象的複製。
如果不知道值類型和引用類型有什麼不同,可以通過這兩個鏈接瞭解
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的對象具體數據,由於爲了圖片更簡單直白,所以沒有畫,望諒解。