【C++设计模式】第五篇:原型模式(Prototype)

注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。

克隆对象的效率革命


1. 模式定义与用途​

核心思想​

  • 原型模式:通过复制现有对象(原型)来创建新对象,而非通过new构造。
  • 关键用途:
    1.减少初始化开销:适用于创建成本高的对象(如数据库连接)。
    2.动态配置对象:运行时通过克隆生成预设配置的实例。

经典场景​

  • 游戏开发:批量生成相同属性的敌人或道具。
  • 文档编辑:复制带格式的文本段落。

2. 模式结构解析​

UML类图

plaintext 复制代码
+---------------------+          +---------------------+  
|    Prototype        |          |       Client        |  
+---------------------+          +---------------------+  
| + clone(): Prototype|<>------->| - prototype: Prototype  
+---------------------+          +---------------------+  
          ^  
          |  
+---------------------+  
| ConcretePrototype   |  
+---------------------+  
| + clone()           |  
+---------------------+  

角色说明​

  • Prototype:抽象接口,声明克隆方法 clone()
  • ConcretePrototype:具体原型类,实现克隆逻辑。
  • Client:通过调用 clone() 创建新对象。

3. 简单示例:基础克隆实现

cpp 复制代码
#include <memory>  

// 抽象原型接口  
class Enemy {  
public:  
    virtual ~Enemy() = default;  
    virtual std::unique_ptr<Enemy> clone() const = 0;  
    virtual void attack() const = 0;  
};  

// 具体原型:骷髅战士  
class SkeletonWarrior : public Enemy {  
public:  
    std::unique_ptr<Enemy> clone() const override {  
        return std::make_unique<SkeletonWarrior>(*this); // 调用拷贝构造函数  
    }  

    void attack() const override {  
        std::cout << "骷髅战士挥舞骨刀!\n";  
    }  
};  

// 使用克隆  
auto original = std::make_unique<SkeletonWarrior>();  
auto clone = original->clone();  
clone->attack();  // 输出:骷髅战士挥舞骨刀!  

4. 完整代码:原型管理器与深拷贝优化

场景:游戏敌人原型注册与批量生成

cpp 复制代码
#include <iostream>  
#include <unordered_map>  
#include <memory>  
#include <string>  

// 抽象敌人原型  
class Enemy {  
public:  
    virtual ~Enemy() = default;  
    virtual std::unique_ptr<Enemy> clone() const = 0;  
    virtual void spawn() const = 0;  
    virtual void setHealth(int health) = 0;  
};  

// 具体原型:火焰恶魔  
class FireDemon : public Enemy {  
public:  
    FireDemon(int health, const std::string& color)  
        : health_(health), color_(color) {}  

    std::unique_ptr<Enemy> clone() const override {  
        return std::make_unique<FireDemon>(*this);  
    }  

    void spawn() const override {  
        std::cout << "生成" << color_ << "火焰恶魔(生命值:" << health_ << ")\n";  
    }  

    void setHealth(int health) override {  
        health_ = health;  
    }  

private:  
    int health_;  
    std::string color_;  
};  

// 原型管理器(注册表)  
class PrototypeRegistry {  
public:  
    void registerPrototype(const std::string& key, std::unique_ptr<Enemy> prototype) {  
        prototypes_[key] = std::move(prototype);  
    }  

    std::unique_ptr<Enemy> createEnemy(const std::string& key) {  
        auto it = prototypes_.find(key);  
        if (it != prototypes_.end()) {  
            return it->second->clone();  
        }  
        return nullptr;  
    }  

private:  
    std::unordered_map<std::string, std::unique_ptr<Enemy>> prototypes_;  
};  

// 客户端代码  
int main() {  
    PrototypeRegistry registry;  

    // 注册原型  
    registry.registerPrototype("red_demon", std::make_unique<FireDemon>(100, "红色"));  
    registry.registerPrototype("blue_demon", std::make_unique<FireDemon>(80, "蓝色"));  

    // 批量生成敌人  
    auto enemy1 = registry.createEnemy("red_demon");  
    auto enemy2 = registry.createEnemy("blue_demon");  
    auto enemy3 = registry.createEnemy("red_demon");  

    enemy1->spawn();  // 生成红色火焰恶魔(生命值:100)  
    enemy2->spawn();  // 生成蓝色火焰恶魔(生命值:80)  
    enemy3->setHealth(50);  
    enemy3->spawn();  // 生成红色火焰恶魔(生命值:50)  
}  

5. 优缺点分析

优点 ​​缺点
​避免重复初始化复杂对象 需正确处理深拷贝(尤其含指针成员时)
动态添加/删除原型配置 每个类需实现克隆方法,增加代码量
与工厂模式结合扩展性强 对简单对象可能得不偿失

6. 调试与优化策略

调试技巧(VS2022)​​

1.深拷贝验证

  • 在拷贝构造函数中设置断点,观察成员变量是否被正确复制。
  • 使用 内存断点 检测指针成员是否被重复释放。

2.​原型注册表检查

  • 输出注册表的键列表,确认原型是否成功注册。
cpp 复制代码
for (const auto& pair : prototypes_) {  
    std::cout << "已注册原型: " << pair.first << "\n";  
}  

性能优化​

1.原型预初始化

  • 在程序启动时预加载常用原型,减少运行时开销。

2.浅拷贝优化

  • 对只读数据成员使用浅拷贝(需确保生命周期安全)。
cpp 复制代码
class CheapToCopyEnemy : public Enemy {  
private:  
    const Texture* sharedTexture_;  // 只读资源,浅拷贝  
};  
相关推荐
越甲八千2 分钟前
C++海康相机DEMO
开发语言·c++·数码相机
天若有情67321 分钟前
用 C++ 实现选择题答案随机生成器:从生活灵感走向代码实践
c++·算法·生活
L73S3726 分钟前
C/C++输入输出(1)
c++·笔记·学习·考研·蓝桥杯
Halsey Walker1 小时前
QT实现简约美观的动画Checkbox
c++·qt·动画
炬火初现1 小时前
仿mudou库one thread oneloop式并发服务器
服务器·c++·muduo
乄北城以北乀1 小时前
muduo库源码分析:TcpConnection 类
linux·数据结构·c++·后端·网络协议·tcp/ip·visual studio
黄明基2 小时前
设计模式学习:2、状态模式实现订单状态流转
设计模式·.net·dotnet core
wen__xvn2 小时前
每日一题蓝桥杯P8598 [蓝桥杯 2013 省 AB] 错误票据c++
开发语言·数据结构·c++·算法
JuicyActiveGilbert2 小时前
【C++设计模式】第一篇:单例模式(Singleton)
c++·单例模式·设计模式
小马爱打代码2 小时前
设计模式详解(单例模式)
java·单例模式·设计模式