跳转到内容

C++ 原型模式

来自代码酷

模板:Note

简介[编辑 | 编辑源代码]

原型模式是一种创建型设计模式,它通过复制现有对象(原型)来创建新对象,而非通过类实例化。该模式的核心思想是:当直接创建对象的成本较高时(如需要复杂初始化或资源消耗大),可以通过克隆已有对象来高效生成新实例。

在C++中,原型模式通常通过实现clone()方法来实现,该方法返回当前对象的一个副本。

模式结构[编辑 | 编辑源代码]

原型模式包含以下角色:

  • Prototype(抽象原型):声明克隆接口的抽象类或接口
  • ConcretePrototype(具体原型):实现克隆操作的具体类
  • Client(客户端):通过请求原型克隆新对象

classDiagram class Prototype { +clone() Prototype* } class ConcretePrototype { -memberData: type +clone() Prototype* } Prototype <|-- ConcretePrototype

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++中一种强大的对象创建技术,特别适用于:

  • 需要创建的对象类型在运行时确定
  • 避免构建与产品类层次平行的工厂类层次
  • 类的实例只能有几个不同状态组合时

正确实现原型模式需要注意拷贝语义(特别是深拷贝问题),并考虑将其与其他创建型模式结合使用以获得最佳效果。