——————————————————————————————————————
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
角色及职责:
-
客户(Client)角色:客户类提出创建对象的请求。
-
抽象原型(Prototype)角色:这是一个抽象角色,通常由一个C#接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在C#中,抽象原型角色通常实现了ICloneable接口。
-
具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象原型角色所要求的接口
-
原型管理器(Prototype Manager)角色:创建具体原型类的对象,并记录每一个被创建的对象
优点:引入Prototype模式后不再需要一个与具体产品等级结构平行的工厂方法类,减少了类的构造,同时客户程序可以在运行时刻建立和删除原型(自定义界面时,此点尤其重要)。
要实现深拷贝,可以通过序列化的方式。抽象类及具体类都必须标注为可序列化的[Serializable]
实现要点:
- 使用原型管理器,体现在一个系统中原型数目不固定时,可以动态的创建和销毁,如上面的举的调色板的例子。
- 实现克隆操作,在.NET中可以使用Object类的MemberwiseClone()方法来实现对象的浅表拷贝或通过序列化的方式来实现深拷贝。
- Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有稳定的接口。
效果:
- 它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。
- Prototype模式允许客户只通过注册原型实例就可以将一个具体产品类并入到系统中,客户可以在运行时刻建立和删除原型。
- 减少了子类构造,Prototype模式是克隆一个原型而不是请求工厂方法创建一个,所以它不需要一个与具体产品类平行的Creater类层次。
- Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。
- 产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构
- Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。
适用性:
- 当一个系统应该独立于它的产品创建,构成和表示时;
- 当要实例化的类是在运行时刻指定时,例如,通过动态装载;
- 为了避免创建一个与产品类层次平行的工厂类层次时;
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
附注:
Prototype模式同工厂模式,同样对客户隐藏了对象的创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的,达到了"隔离类对象的使用者和具体类型(易变类)之间的耦合关系"的目的。
此处引入的知识点式浅拷贝与深拷贝的问题:
概念:
a.浅拷贝(Shallow Copy影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用。
b.深拷贝(Deep Copy深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.完全产生新对象。
深拷贝与浅拷贝实现机制:
对于值类型:
a.浅拷贝: 通过赋值等操作直接实现,将对象中的值类型的字段拷贝到新的对象中。
b.深拷贝:通过赋值等操作直接实现,将对象中的值类型的字段拷贝到新的对象中。 和浅拷贝相同
对于引用类型:
a.浅拷贝: MemberwiseClone方法创建一个浅副本,方法是创建一个新对象,如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用原始对象,与原对象引用同一对象。
b.深拷贝:拷贝对象应用,也拷贝对象实际内容,也就是创建了一个新的改变新对象不会影响到原始对象的内容
这种情况需要为其实现ICloneable接口中提供的Clone方法。
差别就是在对于引用类型的实现深拷贝和浅拷贝的时候的机制不同,前者是MemberwiseClone 方法实现,后者是通过继承实现ICloneable接口中提供的Clone方法,实现对象的深拷贝。
转载自http://www.cnblogs.com/BLoodMaster/archive/2010/03/01/1675856.html,感谢作者的辛勤劳动
如有任何不同的见解,请留言,如果在下还会喘气,会尽快给您答复
示例代码
class CData
{
public:
virtual CData* clone() = 0;
};
class CData_A:public CData
{
public:
virtual CData* clone()
{
return new CData_A;
}
};
class CData_B:public CData
{
public:
virtual CData* clone()
{
return new CData_B;
}
};