C++ 原型模式
外观
简介[编辑 | 编辑源代码]
原型模式是一种创建型设计模式,它通过复制现有对象(原型)来创建新对象,而非通过类实例化。该模式的核心思想是:当直接创建对象的成本较高时(如需要复杂初始化或资源消耗大),可以通过克隆已有对象来高效生成新实例。
在C++中,原型模式通常通过实现clone()
方法来实现,该方法返回当前对象的一个副本。
模式结构[编辑 | 编辑源代码]
原型模式包含以下角色:
- Prototype(抽象原型):声明克隆接口的抽象类或接口
- ConcretePrototype(具体原型):实现克隆操作的具体类
- Client(客户端):通过请求原型克隆新对象
C++实现[编辑 | 编辑源代码]
以下是原型模式的基本实现示例:
#include <iostream>
#include <memory>
// 抽象原型
class Prototype {
public:
virtual ~Prototype() = default;
virtual std::unique_ptr<Prototype> clone() const = 0;
virtual void print() const = 0;
};
// 具体原型
class ConcretePrototype : public Prototype {
int data_;
public:
explicit ConcretePrototype(int data) : data_(data) {}
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<ConcretePrototype>(*this);
}
void print() const override {
std::cout << "ConcretePrototype with data: " << data_ << "\n";
}
};
int main() {
// 创建原型对象
ConcretePrototype original(42);
// 克隆对象
auto clone = original.clone();
std::cout << "Original: ";
original.print();
std::cout << "Clone: ";
clone->print();
return 0;
}
输出[编辑 | 编辑源代码]
Original: ConcretePrototype with data: 42 Clone: ConcretePrototype with data: 42
代码解释[编辑 | 编辑源代码]
1. Prototype
是抽象基类,定义了克隆接口clone()
2. ConcretePrototype
实现了具体的克隆逻辑,通过拷贝构造函数创建新对象
3. 客户端代码通过调用clone()
方法获取对象副本,而不需要知道具体创建细节
深拷贝与浅拷贝[编辑 | 编辑源代码]
在实现原型模式时,必须注意拷贝语义:
- 浅拷贝:仅复制指针值,新旧对象共享同一资源
- 深拷贝:复制指针指向的实际数据,新旧对象拥有独立资源
在大多数情况下,原型模式需要实现深拷贝以确保对象独立性。以下是深拷贝示例:
class DeepCopyPrototype : public Prototype {
int* data_;
public:
explicit DeepCopyPrototype(int data) : data_(new int(data)) {}
// 拷贝构造函数实现深拷贝
DeepCopyPrototype(const DeepCopyPrototype& other)
: data_(new int(*other.data_)) {}
~DeepCopyPrototype() { delete data_; }
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<DeepCopyPrototype>(*this);
}
};
实际应用案例[编辑 | 编辑源代码]
原型模式在以下场景中特别有用:
游戏开发[编辑 | 编辑源代码]
在游戏中创建大量相似但略有不同的对象(如敌人、武器等):
class Enemy : public Prototype {
// 敌人属性...
public:
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<Enemy>(*this);
}
// 其他方法...
};
// 使用时:
Enemy dragonPrototype; // 创建龙的原型
auto dragon1 = dragonPrototype.clone();
auto dragon2 = dragonPrototype.clone();
图形编辑器[编辑 | 编辑源代码]
复制图形对象而无需知道具体类型:
class Graphic : public Prototype {
// 图形属性和方法...
};
class Circle : public Graphic {
// 圆形特有属性和方法...
};
// 客户端代码可以统一处理所有图形的复制
void duplicateSelected(std::vector<std::unique_ptr<Graphic>>& selection) {
std::vector<std::unique_ptr<Graphic>> copies;
for (const auto& graphic : selection) {
copies.push_back(graphic->clone());
}
// 处理复制的图形...
}
优缺点[编辑 | 编辑源代码]
优点[编辑 | 编辑源代码]
- 避免重复初始化开销大的对象
- 隐藏对象创建的复杂性
- 可以动态添加或删除产品类
- 通过改变值来指定新对象(而非通过new)
缺点[编辑 | 编辑源代码]
- 每个类都需要实现克隆方法
- 深拷贝实现可能复杂(尤其当对象包含循环引用时)
- 对已有类修改可能违反开闭原则
与其他模式的关系[编辑 | 编辑源代码]
进阶主题[编辑 | 编辑源代码]
原型注册表[编辑 | 编辑源代码]
可以创建原型对象的注册表(字典),客户端可以通过名称访问和克隆预定义原型:
class PrototypeRegistry {
std::unordered_map<std::string, std::unique_ptr<Prototype>> prototypes_;
public:
void addPrototype(const std::string& key, std::unique_ptr<Prototype> proto) {
prototypes_[key] = std::move(proto);
}
std::unique_ptr<Prototype> clone(const std::string& key) {
return prototypes_.at(key)->clone();
}
};
序列化实现克隆[编辑 | 编辑源代码]
对于复杂对象,可以通过序列化/反序列化实现深度克隆:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
class SerializablePrototype {
// 实现序列化接口...
public:
std::unique_ptr<SerializablePrototype> deepClone() const {
std::stringstream ss;
boost::archive::text_oarchive oa(ss);
oa << *this;
boost::archive::text_iarchive ia(ss);
auto clone = std::make_unique<SerializablePrototype>();
ia >> *clone;
return clone;
}
};
总结[编辑 | 编辑源代码]
原型模式是C++中一种强大的对象创建技术,特别适用于:
- 需要创建的对象类型在运行时确定
- 避免构建与产品类层次平行的工厂类层次
- 类的实例只能有几个不同状态组合时
正确实现原型模式需要注意拷贝语义(特别是深拷贝问题),并考虑将其与其他创建型模式结合使用以获得最佳效果。