定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
类图:
原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:
- 定义父类的Clone方法,申明为纯虚函数。
- 重写父类类中的clone方法。
原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代。
/*
解析:
Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性,
但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个例子来
解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函
数),你需要配什么钥匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙
的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prototype),不
然不知道该配什么样的钥匙.
*/
//声明一个虚拟基类,所有的原型都从这个基类继承,
class prototype
{
public:
prototype(){}
virtual ~prototype(){}
virtual prototype* clone() = 0;//纯虚函数,需要供继承者自行实现
};
// 派生自Prototype,实现Clone方法
class concreateprototype1:public prototype
{
public:
concreateprototype1();
concreateprototype1(const concreateprototype1&);
virtual ~concreateprototype1();
virtual prototype* clone(); //派生类自己实现父类的clone方法
};
// 派生自Prototype,实现Clone方法
class concreateprototype2:public prototype
{
public:
concreateprototype2();
concreateprototype2(const concreateprototype2&);
virtual ~concreateprototype2();
virtual prototype* clone(); //派生类自己实现父类的clone方法
};
原型模式的优点及适用场景
使用原型模式创建对象比直接new一个对象在性能上要好的多,特别是复制大对象时,性能的差别非常明显。
使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
原型模式的注意事项
- 使用原型模式复制对象不会调用类的构造方法。
- 深拷贝与浅拷贝。父类类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
//the pro-class which define the clone method
class Prototype
{
public:
virtual Prototype *Clone() = 0;
virtual void show() = 0;
};
//The first specific class which inherit the pro-class
class Prototype1:public Prototype
{
protected:
string name;
int id;
public:
Prototype1(string name, int id)
{
this->name = name;
this->id = id;
}
Prototype1(const Prototype1&type)
{
this->name = type.name;
this->id = type.id;
}
virtual void show()
{
cout<<"my name and id are : " << this->id<<" "<< this->name <<endl;
}
Prototype *Clone()
{
return new Prototype1(*this);
}
};
//The second specific class which inherit the pro-class
class Prototype2:public Prototype
{
protected:
string name;
public:
Prototype2(string name)
{
this->name = name;
}
Prototype2(const Prototype2&type)
{
this->name = type.name;
}
virtual void show()
{
cout<<"my name is : "<< this->name <<endl;
}
Prototype *Clone()
{
return new Prototype2(*this);
}
};
int main()
{
cout<<"\n--------------start of the main()---------------"<<endl;
Prototype *obj1 = new Prototype1("hello1", 1); //new a specific object and pointed to the pro-class
Prototype *obj2 = obj1->Clone();
Prototype *obj3 = obj2->Clone();
obj1->show();
obj2->show();
obj3->show();
Prototype *obj4 = new Prototype2("hello2");
Prototype *obj5 = obj4->Clone();
Prototype *obj6 = obj5->Clone();
obj4->show();
obj5->show();
obj6->show();
delete obj1;
delete obj2;
delete obj3;
delete obj4;
delete obj5;
delete obj6;
cout<<"\n--------------end of the main()---------------"<<endl;
return 0;
}