概念:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
解释说明:
1.从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
2.在实例化的构造函数执行时间很长,并且初始化的信息不发生变化的情况下,使用克隆技术,
3.不用重新初始化对象,而是动态地获得对象运行时的状态。
4.我们只需要实现ICloneable接口就可以。该接口只有一个Clone()方法。
原型模式结构类图:
个人总结的基本用法:
想要对次创建谁,那谁就是原型,在原型类当中定于原型的属性,方法,最主要的是Clone方法啦,用于创建当前对象的副本,把当前对象的字段复制给新对象,如果字段的值是值类型,则逐位复制,如果是引用类型,则只复制引用,即只复制地址,新对象和被复制的对象指向同一个空间地址。在客户端调用Clone方法
MemberwiseClone()方法中,如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型的,则只复制引用但不复制引用的对象。
浅复制
实例代码:
工作经历类两个属性。
//工作经历类,定义类的两个属性
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 ame;
private string sex;
private string age;
//引用工作经历对象
private WorkExperience work;
//在“简历”类实例化时同时实例化“工作经历”
public Resume(string name)
{
this.name = name;
work = new WorkExperience();
}
//设置工作经历
public void SetWorkExperience(string workDate, string company)
{
work.WorkDate = workDate ;
work.Company = company;
}
//显示
public void Display()
{
//实现接口的方法,用来克隆对象
Console.WriteLine("{0} {1} {2}", name);
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.SetWorkExperience("1998-2000","脸型公司");
Resume b = (Resume)a.Clone();
b.SetWorkExperience("1998-2006", "大笑公司");
Resume c = (Resume)a.Clone();
c.SetWorkExperience("1998-2003", "zz企业");
a.Display();
b.Display();
c.Display();
Console.Read();
}
个人理解:
在原型类中引用了另一个类的对象,同时定义了Clone方法,用于创建本身的副本,在客户端调用Clone方法,但是由于字段是引用类型的,于是就把引用复制了,这样克隆出来的对象和前面的对象指向同一个地址空间。
深复制:
实例代码:
让“工作经历”实现克隆方法。
//工作经历类,定义类的两个属性
//让工作经历类实现IConeable接口
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;}
}
//工作经历类实现克隆方法
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();
}
//提供Clone方法调用的私有构造函数,以便克隆工作经历的数据
private Resume(WorkExperience work)
{
this.work = (WorkExperience)work.Clone();
}
//设置个人信息
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()
{
Resume obj = new Resume(this.work); //调用私有的构造方法,让“工作经历”克隆完成
obj.name = this.name;
obj.sex = this.sex;
obj.age = this.age;
return obj;
}
}
浅复制与深复制的区别?
浅复制没有克隆被引用对象中的数据,只是传了引用。深复制在被引用对象中定义了克隆的方法,用于克隆其中的数据。
下面是我总结的原型模式的由来及之间的关系图:
在原来的方法,我们复制简历的时候,需要实例化多份简历对象,这样就需要多次执行简历类中定义的构造函数,如果每次执行构造函数的时间非常长的话,就会浪费很多的时间,效率会很低。如何改进这种情况呢?那就是尽量避免实例化每一份简历,我们只需要创建第一份简历就行,然后克隆他就可以得到我们想要的其他的简历。
浅复制:
但是当简历中的字段是值类型的时候可以复制过去,但当字段是引用类型的时候我们只是复制了引用,所以每次复制都指向相同的空间,导致所有的引用都是最后一次设置,这就是浅复制。如何解决这个问题呢?那就是深复制:
深复制:
深复制在被引用对象中定义了克隆的方法,用于克隆其中的数据
。