1、有两个主要的原因需要使用“克隆”:必须(或更喜欢)对正在处理的对象的精确类型保持“不知情”;不希望改变被克隆的原始对象,也不希望受原始对象改变的影响。
2、在C++中,提供了这种克隆对象的能力的成员函数,称为“虚构造函数”。
当然,并不存在什么虚构造函数,但是生成对象的一份复制品通常涉及到通过一个虚函数对其类的构造函数的间接调用,因此,即使不是真的虚构造函数,效果上也是虚构造函数了。
最近,这种技术已经被作为Prototype模式的一个实例。
当然,我必须了解所指向的那个对象。在这个例子中,只需要知道所需的是一个Meal就可以了:
class Meal {
public:
virtual ~Meal( );
virtual void eat( ) = 0;
virtual Meal *clone( ) const = 0;
//....
};
Meal类型通过clone成员函数提供了克隆能力。
clone函数实际上是一种专门类型的Factory Method模式,它制造一个适当的产品,同时允许调用代码对上下文和产品类的精确类型保持不知情。
派生于Meal的具体类(也就是那些实际存在的并且列在菜单上的Meal)必须为纯虚clone操作提供一个实现:
class Spaghetti : public Meal {
public:
Spaghetti ( const Spaghetti &); //复制构造函数
void eat( );
Spaghetti *clone ( ) const
{ return new Spaghetti ( *this ); } //调用复制构造函数
//......
};
3、有了这个简单的框架,就可以生成任何类型的Meal的复制品,并且无需知道正在复制的Meal的实际类型的细节。
注意,以下代码没有提及具体派生类,因为代码不会和任何当前(或将出现)的Meal派生类耦合。
const Meal *m = thatGuyMeal( );
Meal *myMeal = m->clone( );
4、实际上,使用Prototype模式,对一个类型的存在不知情并不会对创建该类型的对象造成任何障碍。
上面的多态代码可以通过编译并发布,如果以后增加新的Meal类型来增强功能也无需重新编译。