C++设计模式之圆形模式详解
·
原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象(原型)来创建新对象,而无需知道具体的类信息。这种模式特别适合当创建对象的成本较高(如需要复杂初始化)或需要频繁创建相似对象的场景。
原型模式的核心思想
- 通过复制已有实例来生成新实例,而非通过
new关键字直接创建 - 被复制的实例称为"原型",新实例是原型的副本
- 隐藏对象创建的细节,提高创建效率
原型模式的核心角色
- 抽象原型(Prototype):定义复制自身的接口(通常是
clone()方法) - 具体原型(Concrete Prototype):实现复制自身的方法
- 客户端(Client):通过原型的
clone()方法创建新对象
原型模式的实现示例
下面以文档复制为例展示原型模式的实现,文档可以包含文本和图片,我们通过原型模式快速复制文档:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// 抽象原型类
class DocumentPrototype {
public:
virtual std::unique_ptr<DocumentPrototype> clone() const = 0;
virtual void addContent(const std::string& content) = 0;
virtual void show() const = 0;
virtual ~DocumentPrototype() = default;
};
// 具体原型类:文本文档
class TextDocument : public DocumentPrototype {
private:
std::string title;
std::vector<std::string> paragraphs;
public:
TextDocument(const std::string& docTitle) : title(docTitle) {}
// 实现克隆方法
std::unique_ptr<DocumentPrototype> clone() const override {
// 创建当前对象的副本并返回
return std::make_unique<TextDocument>(*this);
}
void addContent(const std::string& content) override {
paragraphs.push_back(content);
}
void show() const override {
std::cout << "文本文档: " << title << std::endl;
for (size_t i = 0; i < paragraphs.size(); ++i) {
std::cout << "段落 " << (i + 1) << ": " << paragraphs[i] << std::endl;
}
}
};
// 具体原型类:图文文档
class ImageDocument : public DocumentPrototype {
private:
std::string title;
std::vector<std::string> texts;
std::vector<std::string> images;
public:
ImageDocument(const std::string& docTitle) : title(docTitle) {}
// 实现克隆方法
std::unique_ptr<DocumentPrototype> clone() const override {
return std::make_unique<ImageDocument>(*this);
}
void addContent(const std::string& content) override {
// 简单判断内容是文本还是图片
if (content.substr(0, 5) == "image") {
images.push_back(content);
} else {
texts.push_back(content);
}
}
void show() const override {
std::cout << "图文文档: " << title << std::endl;
for (size_t i = 0; i < texts.size(); ++i) {
std::cout << "文本 " << (i + 1) << ": " << texts[i] << std::endl;
}
for (size_t i = 0; i < images.size(); ++i) {
std::cout << "图片 " << (i + 1) << ": " << images[i] << std::endl;
}
}
};
// 客户端使用
int main() {
// 创建原型文档
auto textDoc = std::make_unique<TextDocument>("会议记录");
textDoc->addContent("项目进度汇报");
textDoc->addContent("讨论了新功能的实现方案");
// 克隆文本文档
auto textDocCopy = textDoc->clone();
textDocCopy->addContent("补充:下周将进行测试");
// 创建图文文档原型
auto imageDoc = std::make_unique<ImageDocument>("产品说明书");
imageDoc->addContent("产品介绍");
imageDoc->addContent("image1: 产品正面图");
imageDoc->addContent("使用方法说明");
// 克隆图文文档
auto imageDocCopy = imageDoc->clone();
imageDocCopy->addContent("image2: 产品侧面图");
// 展示所有文档
std::cout << "===== 原始文本文档 =====" << std::endl;
textDoc->show();
std::cout << "\n===== 复制的文本文档 =====" << std::endl;
textDocCopy->show();
std::cout << "\n===== 原始图文文档 =====" << std::endl;
imageDoc->show();
std::cout << "\n===== 复制的图文文档 =====" << std::endl;
imageDocCopy->show();
return 0;
}
深拷贝与浅拷贝
在原型模式中,克隆对象时需要特别注意拷贝的深度:
- 浅拷贝:只复制对象本身和基本类型成员,引用类型成员只复制指针(默认拷贝构造函数的行为)
- 深拷贝:不仅复制对象本身,还会复制所有引用类型成员所指向的资源
在C++中,如果类包含指针成员或动态分配的资源,需要自定义拷贝构造函数和clone()方法来实现深拷贝,避免多个对象共享同一份资源。
原型模式与工厂模式的区别
- 原型模式:通过复制现有对象创建新对象,适合创建相似但有细微差别的对象
- 工厂模式:通过工厂类创建新对象,适合根据类型创建不同的对象
原型模式的应用场景
- 对象创建成本高(如需要读取数据库、文件等)
- 需要频繁创建相似对象(如游戏中的敌人、粒子系统)
- 不确定具体类型的情况下创建对象
- 避免构造函数的限制,通过复制绕过复杂的初始化过程
原型模式的优缺点
优点:
- 提高对象创建效率,尤其是创建复杂对象时
- 简化对象创建过程,隐藏创建细节
- 便于动态添加或删除产品
- 允许在运行时动态改变具体的产品类型
缺点:
- 需要为每个类实现
clone()方法,增加代码维护成本 - 深拷贝实现复杂,容易出错
- 可能会隐藏对象创建的具体细节,增加代码理解难度
原型模式在C++标准库中也有应用,例如std::shared_ptr和std::unique_ptr的拷贝行为,以及容器的复制构造函数等,都是原型模式思想的体现。
更多推荐


所有评论(0)