【C++】原型模式

发布于:2025-06-21 ⋅ 阅读:(19) ⋅ 点赞:(0)

原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有对象(原型)来创建新对象,而无需依赖显式的类实例化过程。这种模式特别适用于创建成本较高或实例化过程复杂的对象,通过克隆现有对象可以显著提高性能。

一、模式结构与核心角色

原型模式包含以下核心角色:

  1. 抽象原型(Prototype):定义克隆自身的接口。
  2. 具体原型(Concrete Prototype):实现克隆方法,返回自身的副本。
  3. 客户端(Client):通过调用原型对象的克隆方法来创建新对象。

二、实现要点

  1. 抽象原型接口:声明克隆方法,通常为纯虚函数,例如:

    class Prototype 
    {
    public:
        virtual Prototype* clone() const = 0;
        virtual ~Prototype() {}
    };
    
  2. 具体原型实现:实现克隆方法,返回自身的副本,例如:

    class ConcretePrototype : public Prototype 
    {
    private:
        int data;
    public:
        ConcretePrototype(int value) : data(value) {}
        
        // 深拷贝实现
        Prototype* clone() const override 
        {
            return new ConcretePrototype(data);
        }
    };
    
  3. 客户端使用:通过克隆现有对象创建新对象,例如:

    Prototype* prototype = new ConcretePrototype(10);
    Prototype* clone = prototype->clone();
    

三、深拷贝与浅拷贝

在实现原型模式时,需要特别注意深拷贝(Deep Copy)和浅拷贝(Shallow Copy)的区别:

  • 浅拷贝:只复制对象本身和基本数据类型,引用类型(如指针、引用)指向原对象的内存地址。
  • 深拷贝:复制对象及其所有引用类型的内容,创建独立的内存副本。

示例(深拷贝)

class Prototype 
{
protected:
    std::string* data;
public:
    Prototype(const std::string& value) : data(new std::string(value)) {}
    
    // 深拷贝构造函数
    Prototype(const Prototype& other) : data(new std::string(*other.data)) {}
    
    ~Prototype() { delete data; }
    
    virtual Prototype* clone() const = 0;
};

class ConcretePrototype : public Prototype 
{
public:
    ConcretePrototype(const std::string& value) : Prototype(value) {}
    
    // 深拷贝克隆方法
    Prototype* clone() const override 
    {
        return new ConcretePrototype(*this);
    }
};

四、原型管理器(Prototype Manager)

当系统中有多个原型对象时,可以使用原型管理器集中管理这些原型:

#include <unordered_map>
#include <string>

class PrototypeManager 
{
private:
    std::unordered_map<std::string, Prototype*> prototypes;

public:
    void addPrototype(const std::string& key, Prototype* prototype)
    {
        prototypes[key] = prototype;
    }
    
    Prototype* getPrototype(const std::string& key) 
    {
        return prototypes[key]->clone();
    }
    
    ~PrototypeManager() 
    {
        for (auto& pair : prototypes) 
        {
            delete pair.second;
        }
    }
};

五、应用场景

  1. 对象创建成本高:当对象的初始化过程涉及复杂计算、IO 操作或网络请求时,例如:
    • 数据库连接对象。
    • 加载大文件的文档对象。
  2. 动态创建对象:在运行时根据需要动态创建对象,例如:
    • 游戏中的角色复制。
    • 配置对象的克隆。
  3. 避免继承层级过深:通过克隆现有对象而非创建子类来定制对象。

六、示例代码:图形克隆系统

以下是一个图形克隆系统的示例,使用原型模式:

#include <iostream>
#include <unordered_map>
#include <memory>

// 抽象原型:图形
class Shape 
{
protected:
    std::string type;

public:
    virtual ~Shape() {}
    std::string getType() const { return type; }
    virtual void draw() const = 0;
    virtual Shape* clone() const = 0;
};

// 具体原型:圆形
class Circle : public Shape 
{
public:
    Circle() { type = "Circle"; }
    void draw() const override { std::cout << "Drawing a circle." << std::endl; }
    Shape* clone() const override { return new Circle(*this); }
};

// 具体原型:矩形
class Rectangle : public Shape 
{
public:
    Rectangle() { type = "Rectangle"; }
    void draw() const override { std::cout << "Drawing a rectangle." << std::endl; }
    Shape* clone() const override { return new Rectangle(*this); }
};

// 原型管理器
class ShapeCache 
{
private:
    std::unordered_map<std::string, Shape*> shapeMap;

public:
    ~ShapeCache() 
    {
        for (auto& pair : shapeMap) 
        {
            delete pair.second;
        }
    }

    Shape* getShape(const std::string& shapeId)
    {
        Shape* cachedShape = shapeMap[shapeId];
        return cachedShape->clone();
    }

    void loadCache() 
    {
        Circle* circle = new Circle();
        shapeMap["Circle"] = circle;

        Rectangle* rectangle = new Rectangle();
        shapeMap["Rectangle"] = rectangle;
    }
};

// 客户端代码
int main() 
{
    ShapeCache shapeCache;
    shapeCache.loadCache();

    // 克隆圆形
    std::unique_ptr<Shape> clonedCircle(shapeCache.getShape("Circle"));
    clonedCircle->draw();  // 输出: Drawing a circle.

    // 克隆矩形
    std::unique_ptr<Shape> clonedRectangle(shapeCache.getShape("Rectangle"));
    clonedRectangle->draw();  // 输出: Drawing a rectangle.

    return 0;
}

七、优缺点

优点:

  • 提高性能:避免重复初始化过程,直接复制现有对象。
  • 简化对象创建:无需依赖具体类,通过接口克隆对象。
  • 动态添加或删除原型:运行时可以灵活管理原型对象。

缺点:

  • 实现复杂:需要正确实现深拷贝,尤其是涉及指针或引用时。
  • 克隆方法传播:每个子类都需要实现克隆方法,可能导致代码冗余。

八、与其他模式的关系

  1. 工厂模式:工厂模式通过工厂类创建对象,而原型模式通过克隆现有对象创建新对象。
  2. 抽象工厂模式:抽象工厂模式可以结合原型模式,通过克隆方法创建产品族。
  3. 构建器模式:构建器模式注重分步构建复杂对象,而原型模式注重复制现有对象。

九、C++ 实现注意事项

  1. 虚析构函数:确保抽象原型类有虚析构函数,防止内存泄漏。
  2. 移动语义:在 C++11 及以后,可以使用移动构造函数和移动赋值运算符优化深拷贝性能。
  3. 智能指针:考虑使用智能指针(如std::unique_ptrstd::shared_ptr)管理克隆对象的生命周期。

原型模式是 C++ 中处理复杂对象创建的有效工具,尤其适用于需要频繁创建相似对象的场景,通过复制现有对象可以显著提高效率和代码灵活性。


如果这篇文章对你有所帮助,渴望获得你的一个点赞!

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到