定义
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然只想原来的对象。
通俗的来说:对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。
深复制:把引用的变量指向复制的新对象,而不是原有的被引用的对象。
通俗的来说:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
如果不知道值类型和引用类型有什么不同,可以通过这两个链接了解
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的对象具体数据,由于为了图片更简单直白,所以没有画,望谅解。