C++设计模式---原型模式

1、介绍

        原型模式(Prototype Pattern)是一种创建型设计模式,它利用已有对象作为原型,通过复制原型对象来创建新的对象。在这个过程中,不需要重新初始化新对象,而是直接复制原型对象的数据和结构,因此可以显著提高性能。原型模式特别适用于需要创建大量相似对象的情况,或者对象的创建过程非常耗时和资源密集。

需要满足以下条件:

        (1)定义一个基类,其中包含一个clone纯虚函数,用于复制当前对象并返回新对象的指针。

        (2)创建一个或多个派生类,实现clone函数,该函数应返回当前对象的动态分配副本。

        (3)客户端代码通过调用clone函数来创建新对象,而不是直接实例化目标类。

        原型模式有两种克隆方式:浅克隆和深克隆。浅克隆只复制对象本身和对象中的值类型字段,对于引用类型字段,只复制引用但不复制引用的对象。而深克隆则复制对象本身和对象中的所有字段,包括引用类型字段引用的对象。

使用场景:

        (1)资源优化。

        (2)性能和安全要求的场景。

        (3)对象状态保存和恢复。

        (4)避免使用分层次的工厂类。

        (5)对象需要频繁修改的场景。

2、浅拷贝【如果类中有指针类型的变量,不推荐使用】

        浅拷贝只会复制对象本身的属性值(如果是指针类型,则只复制指针地址,而不是指针指向的数据)。这可能会导致两个对象共享同一个底层数据资源,从而产生问题。

#include   
#include   
  
class Prototype {  
public:  
    // 构造函数  
    Prototype(const char* data) : ptr(new char[strlen(data) + 1]) {  
        strcpy(ptr, data);  
    }  
  
    // 浅拷贝的拷贝构造函数  
    Prototype(const Prototype& other) {  
        ptr = other.ptr; // 直接复制指针地址,未复制实际数据  
    }  
  
    ~Prototype() {  
        delete[] ptr; // 释放内存。这里也会出现double free的问题
    }  
  
    // 克隆函数(浅拷贝)  
    Prototype* clone() const {  
        return new Prototype(*this); // 调用拷贝构造函数进行浅拷贝  
    }  
  
    void display() const {  
        std::cout << &ptr << "   " << (void*)ptr << "   " << ptr << std::endl;  
    }  
  
private:  
    char* ptr;  
};  
  
int main() {  
    Prototype original("Hello");  
    Prototype copy = original;           // 使用拷贝构造函数进行浅拷贝  
    Prototype* copy1 = original.clone(); // 使用clone函数进行浅拷贝  
  
    original.display(); // 输出 "Hello"  
    copy.display();     // 输出 "Hello"  
    copy1->display();   // 输出 "Hello"  
    // 释放original、copy、copy1的时候会出现double free的问题。
    // 因为ptr是同一个指针,在析构的时候会被释放两次。
  
    return 0;  
}

结果:

0x7ffdb18e4480   0x17e3c20   Hello
0x7ffdb18e4478   0x17e3c20   Hello
0x17e3c40   0x17e3c20   Hello
*** Error in `./shejimoshi-yuanxingmoshi': double free or corruption (fasttop): 0x0000000000a86c20 ***

3、深拷贝【推荐使用】

        深拷贝会复制对象本身的属性值,并且如果属性是指针类型,则还会复制指针指向的数据。这确保了两个对象有各自独立的数据资源。

#include   
#include   
  
class Prototype {  
public:  
    Prototype(const char* data) : ptr(new char[strlen(data) + 1]) {  
        strcpy(ptr, data);  
    }  
  
    // 深拷贝的拷贝构造函数  
    Prototype(const Prototype& other) : ptr(new char[strlen(other.ptr) + 1]) {  
        strcpy(ptr, other.ptr); // 复制实际数据,而不是指针地址  
    }  
  
    // 赋值运算符重载(也实现深拷贝)  
    Prototype& operator=(const Prototype& other) {  
        if (this != &other) {  
            delete[] ptr;       // 释放旧数据  
            ptr = new char[strlen(other.ptr) + 1];  
            strcpy(ptr, other.ptr);  
        }  
        return *this;  
    }  
  
    ~Prototype() {  
        delete[] ptr;           // 释放内存  
    }  
  
    // 克隆函数(深拷贝)  
    Prototype* clone() const {  
        return new Prototype(*this); // 调用拷贝构造函数进行深拷贝  
    }  
  
    void display() const {  
        std::cout << &ptr << "   " << (void*)ptr << "   " << ptr << std::endl;  
    }  
  
private:  
    char* ptr;  
};  
  
int main() {  
    Prototype original("Hello");  
    Prototype copy = original;           // 使用拷贝构造函数进行深拷贝  
    Prototype* copy1 = original.clone(); // 调用clone()函数进行深拷贝  
  
    original.display(); // 输出 "Hello"  
    copy.display();     // 输出 "Hello" 
    copy1->display();   // 输出 "Hello"
  
    // 此时,original和copy各自拥有独立的内存资源;释放内存时无问题。
  
    return 0;  
}

结果:

0x7ffda1e00340   0x1aa7c20   Hello
0x7ffda1e00338   0x1aa7c40   Hello
0x1aa7c60   0x1aa7c80   Hello

你可能感兴趣的:(设计模式,c++,设计模式,原型模式)