#include <iostream>
#include <string>
using namespace std;
// Prototype 基类
class Prototype {
public:
virtual Prototype* clone() const = 0;
virtual void print() const = 0;
virtual ~Prototype() {}
};
// ConcretePrototype 具体类,包含一个指针成员
class ConcretePrototype : public Prototype {
private:
string* data;
public:
// 构造函数
ConcretePrototype(const string& value) {
data = new string(value);
}
// 拷贝构造函数,实现深拷贝
ConcretePrototype(const ConcretePrototype& other) {
data = new string(*other.data);
}
// 重写 clone 方法,使用拷贝构造函数来实现深拷贝
Prototype* clone() const override {
return new ConcretePrototype(*this);
}
// 打印数据
void print() const override {
cout << "Data: " << *data << endl;
}
// 析构函数
~ConcretePrototype() {
delete data;
}
};
int main() {
// 创建原型对象
Prototype* prototype = new ConcretePrototype("Prototype");
// 使用原型对象克隆出一个新对象
Prototype* clonedPrototype = prototype->clone();
// 打印原型和克隆对象的数据
prototype->print();
clonedPrototype->print();
// 清理资源
delete prototype;
delete clonedPrototype;
return 0;
}
工作过程:
- 定义一个原型接口(
Prototype
),该接口声明了一个clone
方法。 - 创建一个具体原型类(
ConcretePrototype
),实现原型接口。ConcretePrototype
包含一个拷贝构造函数,用于创建当前对象的副本。 - 客户端创建一个原型对象,并通过调用
clone
方法来复制这个对象。
使用场景:
- 当直接创建一个对象的实例过于复杂或成本过高时,例如当对象的创建依赖于外部资源或者初始化过程非常复杂时。
- 当需要大量相似对象时,使用原型模式可以减少子类的数量。
优点:
- 提高性能:通过复制已有对象来避免了类初始化时的消耗。
- 简化对象的创建:尤其是当对象类型只有在运行时才确定时,原型模式可以不通过子类化即可动态添加或删除产品。
- 灵活性高:可以在运行时通过克隆已有的实例来生成新的实例。
以上示例展示了原型模式在Qt中的实现。这种模式适用于对象创建成本较高的场景,它通过复制已有对象来避免这种成本,提高了应用程序的效率和灵活性。
个人总结:
在clone函数中使用了深拷贝来对成员变量中的指针进行了复制,本质上是使用拷贝构造函数来避免生成一个新的对象。