C++实现设计模式---原型模式 (Prototype)

原型模式 (Prototype)

原型模式 是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化。


意图

  • 使用原型实例指定要创建的对象类型,并通过复制该原型来生成新对象。
  • 提供一种高效创建对象的方式,尤其是当对象的创建成本较高时。

使用场景

  1. 对象创建成本高
    • 如果直接实例化对象开销较大(如对象初始化需要大量资源),可以通过克隆已存在的对象快速生成新实例。
  2. 复杂对象需要重复创建
    • 当对象的结构较复杂,需要创建多个相似对象时。
  3. 避免直接依赖具体类
    • 原型模式通过复制实例而不是直接依赖构造函数,可以减少对具体类的依赖。

参与者角色

  1. 原型接口 (Prototype)
    • 定义一个克隆方法,用于复制对象。
  2. 具体原型 (Concrete Prototype)
    • 实现原型接口,定义克隆方法,返回当前实例的复制品。
  3. 客户端 (Client)
    • 使用原型接口创建新对象,而不直接依赖具体类。

示例代码

以下示例展示了如何使用原型模式创建几种不同类型的图形对象。

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

// 原型接口
class Shape {
public:
    virtual ~Shape() {}
    virtual std::unique_ptr<Shape> clone() const = 0;
    virtual void draw() const = 0;
};

// 具体原型:圆形
class Circle : public Shape {
private:
    int radius;

public:
    Circle(int r) : radius(r) {}

    // 实现克隆方法
    std::unique_ptr<Shape> clone() const override {
        return std::make_unique<Circle>(*this);
    }

    void draw() const override {
        std::cout << "Drawing a Circle with radius: " << radius << std::endl;
    }
};

// 具体原型:矩形
class Rectangle : public Shape {
private:
    int width, height;

public:
    Rectangle(int w, int h) : width(w), height(h) {}

    // 实现克隆方法
    std::unique_ptr<Shape> clone() const override {
        return std::make_unique<Rectangle>(*this);
    }

    void draw() const override {
        std::cout << "Drawing a Rectangle with width: " << width
                  << " and height: " << height << std::endl;
    }
};

// 客户端代码
int main() {
    // 创建具体原型
    std::unique_ptr<Shape> circlePrototype = std::make_unique<Circle>(10);
    std::unique_ptr<Shape> rectanglePrototype = std::make_unique<Rectangle>(20, 30);

    // 克隆原型
    auto circle1 = circlePrototype->clone();
    auto circle2 = circlePrototype->clone();

    auto rectangle1 = rectanglePrototype->clone();

    // 使用克隆对象
    circle1->draw(); // 输出:Drawing a Circle with radius: 10
    circle2->draw(); // 输出:Drawing a Circle with radius: 10
    rectangle1->draw(); // 输出:Drawing a Rectangle with width: 20 and height: 30

    return 0;
}

代码解析

1. 原型接口

  • 定义了 clone() 方法,用于创建当前对象的副本:
cpp 复制代码
virtual std::unique_ptr<Shape> clone() const = 0;

2. 具体原型类

  • CircleRectangle 是具体原型类,分别实现了 clone() 方法,返回自身的副本:
cpp 复制代码
std::unique_ptr<Shape> clone() const override {
    return std::make_unique<Circle>(*this);
}

3. 客户端

  • 客户端通过调用 clone() 方法创建对象,而无需直接依赖具体类:
cpp 复制代码
auto circle1 = circlePrototype->clone();
circle1->draw();

优缺点

优点

  1. 对象复制高效
    • 直接复制对象比重新实例化速度更快。
  2. 减少依赖
    • 客户端代码无需依赖具体类的构造函数。
  3. 动态创建对象
    • 可在运行时动态生成对象,而不是在编译时确定。

缺点

  1. 深拷贝复杂性
    • 如果对象中包含指针或其他复杂资源,需特别注意深拷贝逻辑。
  2. 实现复杂
    • 需要为每个类实现 clone() 方法,增加了一定的代码量。

适用场景

  • 需要大量相似对象:如图形编辑器中需要重复创建类似图形。
  • 对象初始化成本高:如大型游戏中加载模型、地图等资源。
  • 需要动态生成对象:如根据配置文件动态生成对象。

改进与扩展

  1. 深拷贝支持

    • 如果对象包含动态内存或指针成员变量,需要实现深拷贝以避免资源共享问题。
  2. 结合原型注册表

    • 使用注册表保存所有原型实例,根据名称或类型动态克隆对象:
    cpp 复制代码
    class PrototypeRegistry {
    private:
        std::unordered_map<std::string, std::unique_ptr<Shape>> prototypes;
    
    public:
        void registerPrototype(const std::string& name, std::unique_ptr<Shape> prototype) {
            prototypes[name] = std::move(prototype);
        }
    
        std::unique_ptr<Shape> create(const std::string& name) const {
            return prototypes.at(name)->clone();
        }
    };

总结

原型模式通过复制已有对象来快速创建新对象,避免了复杂的初始化逻辑,并减少了对具体类的依赖。

它适用于需要动态生成大量相似对象或高效创建对象的场景。

相关推荐
Q741_14721 分钟前
每日一题 力扣 3655. 区间乘法查询后的异或 II 模拟 分治 乘法差分法 快速幂 C++ 题解
c++·算法·leetcode·模拟·快速幂·分治·差分法
夏乌_Wx26 分钟前
剑指offer | 2.4数据结构相关题目
数据结构·c++·算法·剑指offer·c/c++
米啦啦.28 分钟前
C+类的友元与静态成员函数,类模板
c++·友元·类模板
超绝振刀怪33 分钟前
【C++可变模板参数】
开发语言·c++·可变模板参数
minji...1 小时前
Linux 线程同步与互斥(二) 线程同步,条件变量,pthread_cond_init/wait/signal/broadcast
linux·运维·开发语言·jvm·数据结构·c++
梓䈑1 小时前
高性能 C++ 日志实战:spdlog 核心架构解析与最佳实践指南
c++·架构
qqxhb1 小时前
26|Agent 设计模式:ReAct、Plan-and-Solve 与反射
设计模式·react模式·plan-and-solve·reflection模式
草莓熊Lotso2 小时前
【Linux 线程进阶】进程 vs 线程资源划分 + 线程控制全详解
java·linux·运维·服务器·数据库·c++·mysql
唐樽2 小时前
C++ 竞赛学习路线笔记
c++·笔记·学习
ShineWinsu2 小时前
对于Linux:文件操作以及文件IO的解析
linux·c++·面试·笔试·io·shell·文件操作