【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 框架在保证对象独立性的同时,显著优化了内存使用和对象创建效率,尤其适用于需要频繁复制或共享资源的场景。

相关推荐
橙色小博7 分钟前
利用Python 进行自动化操作: Pyautogui 库
开发语言·python·自动化·pyautogui·办公
qq_5432485221 分钟前
redis的哨兵模式和Redis cluster
java·开发语言
IUings27 分钟前
【鸿蒙】HarmonyOS NEXT之如何正常加载地图组件
开发语言·华为·harmonyos·harmonyos next·地图服务·map kit
秦少游在淮海44 分钟前
C++ - STL #什么是STL #STL的版本 #闭源开源 #STL的六大组件
开发语言·c++
夜月yeyue1 小时前
高性能MCU的MPU与Cache优化详解
linux·开发语言·stm32·单片机·嵌入式硬件
Wyn_1 小时前
【QT】自定义QWidget标题栏,可拖拽(拖拽时窗体变为normal大小),可最小/大化、关闭(图文详情)
开发语言·qt
“抚琴”的人1 小时前
【机械视觉】Halcon—【六、交集并集差集和仿射变换】
开发语言·halcon
VBA63371 小时前
VBA数据库解决方案二十:Select表达式From区域Where条件Order by
开发语言
Haoea!1 小时前
Flink03-学习-套接字分词流自动写入工具
开发语言·学习
@Turbo@2 小时前
【QT】在Qt6的`QTextEdit`中,同一行更新内容
开发语言·qt