原型设计模式的学习

哪位大佬帮我看看关于“原型设计模式”的问题

写作原因:

我需要了解原型模式,但网上的说法是:通过一个clone方法来创建对象。然而,这并没有解答关于“效率”的问题:

以下是以怪物游戏和深拷贝为例来说明的:

  1. 为什么使用这种模式来创建大量怪物效率会更高?难道不是都通过new来创建的吗?自定义的clone方法难道不是在底层调用new,与直接调用new相比效率有显著差异吗?
  2. 无论使用何种方法,每个怪物的大小都是一样的,为什么克隆拷贝会比新建实例更快?而且并没有使用多线程或多进程。

总体来说一个句话概况:为什么克隆拷贝会比新建实例更快?


于是我让GPT创建了一个 原型设计模式 的测试案例

#include <iostream>
#include <string>
#include <chrono>

class ComplexObject {
private:
    std::string data;
public:
    ComplexObject(const std::string& d) : data(d) {
        // 模拟耗时的初始化操作
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << "ComplexObject constructed with data: " << data << std::endl;
    }

    ComplexObject(const ComplexObject& other) : data(other.data) {
        std::cout << "ComplexObject copied with data: " << data << std::endl;
    }

    void setData(const std::string& newData) {
        data = newData;
    }

    void printData() {
        std::cout << "Data: " << data << std::endl;
    }
};

class ObjectPrototype {
private:
    ComplexObject* prototype;
public:
    ObjectPrototype(ComplexObject* obj) : prototype(obj) {}

    ComplexObject* clone() {
        // 通过复制构造函数来创建新对象
        return new ComplexObject(*prototype);
    }
};

int main() {
    // 创建原型对象
    ComplexObject* prototype = new ComplexObject("Prototype Data");

    // 使用原型对象创建新对象
    ObjectPrototype* objPrototype = new ObjectPrototype(prototype);

    // 复制原型对象来创建新对象
    ComplexObject* newObj1 = objPrototype->clone();
    ComplexObject* newObj2 = objPrototype->clone();

    newObj1->printData();
    newObj2->printData();

    delete prototype;
    delete newObj1;
    delete newObj2;
    delete objPrototype;

    return 0;
}

代码分析

ComplexObject 的 拷贝构造速度>构造函数速度 ,因为构造函数中有个延时sleep的操作。所以,原型设计模式的克隆是通过拷贝构造函数实现,而拷贝构造速度>构造函数速度 ,所以 clone > new 。这确实没问题。

代码总结

GPT认为:速度快需要 拷贝构造速度>构造函数速度 才能加速,否则无法加速。

仍然无法加速的情况

上述代码没有考虑到深拷贝的情况。在深拷贝时候,拷贝构造速度构造函数速度可能差不多,就无法加速了。比如下面的代码

案例:深拷贝 + 原型设计模式对比实验

#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <vector>

constexpr auto N = 10000;
constexpr auto NUMBER_OF_People = 1000 ;

class ComplexObject {
private:
    long long  data;
    std::vector<long long> * m_pNumbers = new std::vector<long long>;
public:
    ComplexObject(const long long& d) : data(d) {
        // 用创建大数组模拟耗时的初始化操作
        for (int i = 0; i < N; i ++)
        {
            m_pNumbers->push_back(i);
        }
        (*m_pNumbers)[0] = data;
        std::cout << "ComplexObject constructed with data: " << data << std::endl;
    }

    ComplexObject(const ComplexObject& other, long long id) : data(other.data) {
        // 用深拷贝大数组模拟耗时的初始化操作
        for (int i = 0; i < N; i++)
        {
            m_pNumbers->push_back((*(other.m_pNumbers))[i]);
        }
        (*m_pNumbers)[0] = id;
        std::cout << "ComplexObject copied with data: " << (*m_pNumbers)[0] << std::endl;
    }

    void printData() {
        std::cout << "Data: " << (*m_pNumbers)[0] << std::endl;
    }
};

class ObjectPrototype {
private:
    ComplexObject* prototype;
public:
    ObjectPrototype(ComplexObject* obj) : prototype(obj) {}

    ComplexObject* clone(int id) {
        // 通过复制构造函数来创建新对象
        return new ComplexObject(*prototype,id);
    }
};

// 使用原型设计模式的情况
int main1() {
    std::cout << "Test prototype begin" << std::endl << std::endl;
    // 创建原型对象
    ComplexObject* prototype = new ComplexObject(1);

    // 使用原型对象创建新对象
    ObjectPrototype* objPrototype = new ObjectPrototype(prototype);
    std::vector< ComplexObject*> g_vecPeople;

    // 复制原型对象来创建新对象
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 2; i < NUMBER_OF_People; i++)
    {
        ComplexObject* newObj  = objPrototype->clone(i);
        g_vecPeople.push_back(newObj);
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    double durationInSeconds = duration.count() / 1000000.0; // 转换为秒
    std::cout << "Function execution time: " << durationInSeconds << " seconds" << std::endl;

    for (std::vector< ComplexObject*>::iterator it = g_vecPeople.begin(); it != g_vecPeople.end(); it++)
    {
        if (*it)
        {
            delete* it;
            *it = nullptr;
        }
    }
    g_vecPeople.clear();
    delete prototype;
    delete objPrototype;
    return 0;
}

// 一般的情况
int main() {
    std::cout << "Test STD begin" << std::endl << std::endl;

    // 创建原型对象
    ComplexObject* prototype = new ComplexObject(1);
    std::vector< ComplexObject*> g_vecPeople;

    // 复制原型对象来创建新对象
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 2; i < NUMBER_OF_People; i++)
    {
        ComplexObject* newObj = new ComplexObject(i);
        g_vecPeople.push_back(newObj);
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    double durationInSeconds = duration.count() / 1000000.0; // 转换为秒
    std::cout << "Function execution time: " << durationInSeconds << " seconds" << std::endl;

    for (std::vector< ComplexObject*>::iterator it = g_vecPeople.begin(); it != g_vecPeople.end(); it++)
    {
        if (*it)
        {
            delete* it;
            *it = nullptr;
        }
    }
    g_vecPeople.clear();
    return 0;
}

代码分析

上述代码构造了一种 拷贝构造速度==构造函数速度 的情况,发现没有实现加速。

得到一个奇怪的结论:深拷贝情况下,创立多个对象,似乎原型设计模式无法加速。


更新一下GPT的回答

问:

如果ComplexObject 类的 拷贝构造函数的 和 构造函数速度相同,那使用原型设计模式创建多个对象还有加速的效果吗?

答:

原型设计模式的主要目的是通过复制现有对象来创建新对象,从而避免了使用常规的构造函数来初始化新对象的开销。如果复制构造函数的速度与常规构造函数相同,那么在性能方面可能不会有太大的加速效果。
然而,即使复制构造函数的速度与常规构造函数相同,使用原型设计模式仍然可以带来一些优势:
减少初始化时间:尽管构造函数的速度相同,但使用原型模式可以避免一些初始化步骤,因为新对象可以直接从现有对象复制而来,而不需要重新执行构造函数中的初始化操作。
避免重复的计算和初始化:如果对象的创建涉及到复杂的计算或初始化过程,使用原型模式可以避免重复执行这些计算和初始化步骤,因为新对象可以直接从现有对象复制而来。
灵活性:使用原型模式可以更灵活地创建对象,因为可以根据现有对象的状态来创建新对象,而不受构造函数的限制。
总的来说,尽管在速度方面可能没有显著的加速效果,但使用原型模式仍然可以提高代码的性能和灵活性。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值