-
原型模式:一种创建型设计模式
-
应用场景:
一个基类,有很多派生类,在实际开发中,经常会使用一个基类指针,将其指向不同派生类的实例,以实现多态。
之后经过很长的业务操作之后,需要一个该派生类对象的拷贝,但此时会遇到一个问题,如果将该指针解引用后传入拷贝构造函数,new
时是需要确定对象类型的,但由于C++没有反射机制,此时对象的实际类型可能会很难或无法确定,所以原型模式登场了。举例:
有一个果汁的抽象类和各品种果汁的实现类,我们使用了一个果汁类的基类指针指向了一个派生的葡萄汁实例。在过了很久很久之后,需要创建一份该指针所指向果汁的拷贝,但此时单纯通过这个基类指针是没有办法确定该果汁的品种的,所以我们需要每个品种的果汁类都能提供一个方法,用以获得该品种果汁的拷贝。
-
实现方式:
首先,在基类中添加一个用于派生类拷贝的纯虚函数
Clone()
,每个想要被实例化的派生类都需要去实现该方法。
然后,为了使用户(其他开发人员)能够通过该方法获得当前派生类对象的拷贝,在该方法中调用自身类的拷贝构造函数。
最后,将自身(*this)传入拷贝构造函数。 -
优点:
无需确定基类指针所指向的对象类型,即可获得相同类型的实例,提高了创建效率。 -
缺点:
每个派生类都需要实现Clone()方法,增加了代码量。
以下是原型模式的简易代码实现
#include <iostream>
using namespace std;
//果汁的抽象类
class Juice
{
public:
virtual Juice* Clone() = 0; // 用于对象类型拷贝
virtual void Show() = 0; // 验证果汁类型
};
//派生类
class OrangeJuice : public Juice
{
public:
virtual Juice* Clone()
{
return new OrangeJuice(*this); // 返回当前对象类型的拷贝
}
virtual void Show()
{
cout << "Orange Juice" << endl;
}
};
class LemonJuice : public Juice
{
public:
virtual Juice* Clone()
{
return new LemonJuice(*this);
}
virtual void Show()
{
cout << "Lemon Juice" << endl;
}
};
class AppleJuice : public Juice
{
public:
virtual Juice* Clone()
{
return new AppleJuice(*this);
}
virtual void Show()
{
cout << "Apple Juice" << endl;
}
};
主函数中的使用
#include <iostream>
#include "prototype.h"
using namespace std;
int main()
{
Juice* pJuice = new AppleJuice(); // 基类指针指向派生类对象
pJuice->Show();
/*
* 经过/传递了很久很久之后
* 以至于忘记了或难以确定
* 该基类指针所指向的对象具体类型
*/
Juice* pNewJuice = pJuice->Clone(); // 获取拷贝对象
pNewJuice->Show();
return 0;
}
控制台输出结果
Apple Juice
Apple Juice
网友评论