【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)

应用方式
  • 抽象原型类 :QBrush、QPen 等图形类默认支持隐式共享。
  • 隐式共享:默认拷贝操作共享资源,修改时分离数据。
示例代码
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() 方法 确保样式独立修改,避免影响原对象
自定义类 QSharedData 或 clone() 灵活控制共享策略,支持复杂对象深拷贝

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

相关推荐
代码不停11 分钟前
自动化测试(java)
java·开发语言·selenium·自动化
鬼手点金2 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
爱上网的小舟2 小时前
星际战士2启动错误怎么办?5种游戏报错解决方法
开发语言·php
长沙红胖子Qt3 小时前
Qt+TiePieHS3开发笔记(二):HS3发送器发出内置波形、直连示波器,示波器检测内置波形Demo
qt·示波器·tiepiehs3·发生器·同步发射和示波器采集
阿里嘎多学长3 小时前
2026-10-12 GitHub 热点项目精选
开发语言·程序员·github·代码托管
wangchunyu1144 小时前
Python 数据可视化实战入门教程
开发语言·python·信息可视化
学逆向的5 小时前
C 突破编译器限制
c语言·开发语言·网络安全
jimy16 小时前
C++ 虚函数表:基类和派生类共用一张 vtable 吗?
开发语言·c++
爱吃提升6 小时前
Dev-C++ 5.11 C++断点调试完整教程
开发语言·c++
夜晚回家6 小时前
Python 原始字符串详解 | r 前缀到底让什么不再转义
开发语言·python