后天考大物还有太多不懂,感觉有点不妙啊~~~今天学习的是原型模式。
原型模式(Prototype):
原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
优点及适用场景
使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
注意事项
使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的。
在使用时要特别注意。深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝
实例(简历的深复制):
Resume.cs
class Resume : ICloneable
{
private string name;
private int age;
private string sex;
private WorkExperience work;
public Resume(string name)
{
this.name = name;
work = new WorkExperience();
}
private Resume(WorkExperience work)
{
this.work = (WorkExperience)work.Clone();
}
public void SetPersonalInfo(string sex, int 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.age = this.age;
obj.sex = this.sex;
return obj;
}
}
WorkExperience.cs
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();
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("Tracy");
a.SetPersonalInfo("male", 19);
a.SetWorkExperience("2016-2017", "Tencent");
Resume b = (Resume)a.Clone();
b.SetWorkExperience("2010-2017", "Baidu");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("female", 25);
a.Display();
b.Display();
c.Display();
Console.ReadKey();
}
}
简单地说,原型模式隐藏了对象创建的细节,又对性能有了大大的提升。他不用重新初始化对象,而是动态地获得对象运行时的状态。但需特别注意浅复制与深复制。MemberwiseClone()方法,如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制当前对象,因此,原始对象极其副本引用同一对象。