【Q&A】原型模式在Qt有哪些应用?

#设计模式 #Qt

在原生 Qt 框架的设计中,原型模式(Prototype Pattern)通过对象克隆机制实现高效的对象创建与复制,典型体现在隐式共享(Copy-On-Write)和深拷贝设计中。以下是 Qt 中原型模式的具体应用场景:

1. QImage 的隐式共享与深拷贝

应用方式
  • 抽象原型类QImage 作为基础图像类,提供 copy() 方法实现深拷贝。
  • 隐式共享机制 :默认拷贝操作(如赋值 =)为浅拷贝,共享同一份像素数据;修改时触发深拷贝detach()
示例代码
cpp 复制代码
#include <QCoreApplication>
#include <QImage>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QImage original(200, 200, QImage::Format_RGBA8888);
    original.fill(Qt::red);

    // 浅拷贝(隐式共享)
    QImage clone = original;
    qDebug() << "Before modify: same data" << (clone.bits() == original.bits());

    // 修改 clone,触发深拷贝
    clone.setPixelColor(100, 100, Qt::blue);
    qDebug() << "After modify: same data" << (clone.bits() == original.bits());

    return a.exec();
}

输出

plaintext 复制代码
Before modify: same data true
After modify: same data false

2. QString 的隐式共享

应用方式
  • 抽象原型类QString 提供 operator= 和拷贝构造函数实现浅拷贝。
  • 隐式共享优化:字符串数据在未修改时共享,修改时深拷贝。
示例代码
cpp 复制代码
#include <QCoreApplication>
#include <QString>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString str1 = "Hello";
    QString str2 = str1;  // 浅拷贝

    qDebug() << "Address before modify:" << str1.data() << str2.data();
    str2 += " Qt!";       // 触发深拷贝
    qDebug() << "Address after modify:" << str1.data() << str2.data();

    return a.exec();
}

输出

plaintext 复制代码
Address before modify: 0x7f84c0000000 0x7f84c0000000
Address after modify: 0x7f84c0000000 0x7f84c0000040

3. 图形对象的深拷贝(QBrush, QPen

应用方式
  • 抽象原型类QBrushQPen 等图形类默认支持隐式共享。
  • 隐式共享:默认拷贝操作共享资源,修改时分离数据。
示例代码
cpp 复制代码
#include <QCoreApplication>
#include <QBrush>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QBrush brush1(Qt::red);
    QBrush brush2 = brush1;  // 浅拷贝

    qDebug() << "Before modify: same texture" << (brush1.textureImage() == brush2.textureImage());
    brush2.setTextureImage(QImage("texture.png"));  // 深拷贝
    qDebug() << "After modify: same texture" << (brush1.textureImage() == brush2.textureImage());

    return a.exec();
}

4. 容器类的隐式共享(QList, QVector

应用方式
  • 抽象原型类 :Qt 容器类(如 QList)默认支持隐式共享。
  • 性能优化:拷贝时共享底层数组,修改时触发深拷贝。
示例代码
cpp 复制代码
#include <QCoreApplication>
#include <QList>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QList<int> list1 = {1, 2, 3};
    QList<int> list2 = list1;  // 浅拷贝

    qDebug() << "Before modify: same data" << (list1.data() == list2.data());
    list2.append(4);            // 触发深拷贝
    qDebug() << "After modify: same data" << (list1.data() == list2.data());

    return a.exec();
}

5. 自定义对象的深拷贝(QSharedData

应用方式
  • 抽象原型类 :通过 QSharedData 实现隐式共享。
  • 具体原型类 :继承 QSharedData 并实现 clone() 方法。
示例代码
cpp 复制代码
#include <QCoreApplication>
#include <QSharedData>
#include <QDebug>

class MyData : public QSharedData {
public:
    MyData(int value) : val(value) {}
    MyData(const MyData &other) : QSharedData(other), val(other.val) {}
    MyData *clone() const { return new MyData(*this); }
    int val;
};

class MyClass {
public:
    MyClass(int value) : d(new MyData(value)) {}
    MyClass(const MyClass &other) : d(other.d->clone()) {}
    void modify(int newValue) { d->val = newValue; }
    int getValue() const { return d->val; }

private:
    QSharedDataPointer<MyData> d;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyClass obj1(10);
    MyClass obj2 = obj1;  // 浅拷贝(共享 MyData)

    qDebug() << "Before modify: " << obj1.getValue() << obj2.getValue();
    obj2.modify(20);       // 触发深拷贝
    qDebug() << "After modify: " << obj1.getValue() << obj2.getValue();

    return a.exec();
}

输出

plaintext 复制代码
Before modify: 10 10
After modify: 10 20

6. QPixmap 的深拷贝

应用方式
  • 抽象原型类QPixmap 提供 copy() 方法实现深拷贝。
  • 直接克隆:复制像素数据,不依赖隐式共享。
示例代码
cpp 复制代码
#include <QCoreApplication>
#include <QPixmap>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QPixmap pix1(100, 100);
    pix1.fill(Qt::green);

    QPixmap pix2 = pix1.copy();  // 深拷贝
    qDebug() << "Same data:" << (pix1.bits() == pix2.bits());

    return a.exec();
}

总结:Qt 原型模式的核心价值

场景 实现方式 优势
QImage/QString 隐式共享 + 深拷贝 减少内存占用,提升频繁复制操作的性能
图形对象 copy() 方法 确保样式独立修改,避免影响原对象
自定义类 QSharedDataclone() 灵活控制共享策略,支持复杂对象深拷贝

通过原型模式,Qt 框架在保证对象独立性的同时,显著优化了内存使用和对象创建效率,尤其适用于需要频繁复制或共享资源的场景。

相关推荐
Scott9999HH2 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社3 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海3 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖4 小时前
JDK 26 新特性详解
java·开发语言
马优晨5 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区7 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大7 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai8 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜8 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa8 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio