它是这样被定义的:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
就像有一份写好的简历样本,现在需要复制出N份只有名字或年龄不同其他都相同的简历,怎么做呢?原型模式就好比一台现实生活中的复印机。其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。复印机本身不知道所复印的内容,却一字不差地复印了出来。
原型模式的类型:
创建型模式(还有单件模式、工厂模式、抽象工厂模式、创建者模式)
原型模式的好处有二:
1.比直接new一个对象在性能上要好的多,每new一次都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次执行这个初始化操作效率就很低,而Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
2.简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
所以,一般在初始化的信息不发生变化的情况下,克隆是最好的办法。即当我们在处理一些对象比较简单,并且对象之间的区别很小,可能只是很固定的几个属性不同的时候,使用原型模式更合适。这既隐藏了对象创建的细节,又对性能是大大的提高。不用重新初始化对象,而是动态地获得对象运行时的状态。如果我们并不需要基于现有的对象复制新的对象,或者我们需要的就是一个干净的空对象,那么还是选择工厂模式或者抽象工厂模式了。
原型模式的类图:
根据类图写出原型模式的代码:
//原型类
abstract class Prototype
{
private string id;
public Prototype(string id)
{
this.id = id;
}
public string Id
{
get { return id; }
}
public abstract Prototype Clone();//抽象类关键就是有这样一个Clone方法
}
//具体原型类
class ConcretePrototype1 : Prototype
{
public ConcretePrototype1(string id)
: base(id)
{ }
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();
}
}
客户端代码如下:
static void Main(string[] args)
{
ConcretePrototype1 p1 = new ConcretePrototype1("I");
ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();//克隆类ConcertePrototype1的对象p1就能得到新的实例c1
Console.WriteLine("Cloned:{0}", c1.Id);
Console.Read();
}
深复制与浅复制:
原型模式最大的特点是克隆一个现有的对象,这个克隆的结果有2种,一种是浅复制,另一种是深复制。其区别如下图:
因为MemberwiseClone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型的,则复制引用但不复制引用的对象,因此,原始对象及其复本引用同一对象,这是浅复制;深复制则把要复制的的对象所引用的对象都复制一遍。