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

相关推荐
周Echo周25 分钟前
8、STL中的map和pair使用方法
开发语言·数据结构·c++·考研·算法·leetcode·pat考试
TravisBytes1 小时前
VS Code 配置优化指南
开发语言·c++·python
飞奔的马里奥1 小时前
30天学习Java第六天——super关键字
java·开发语言·学习
四念处茫茫1 小时前
【C语言系列】C语言内存函数
c语言·开发语言·算法·visual studio
不爱敲代码吖1 小时前
Python 数据可视化创意工坊:从交互到艺术,解锁数据展示新灵感
开发语言·python·信息可视化
H2X7_1 小时前
C++之list类(超详细)
开发语言·c++
stevenzqzq2 小时前
java常量池
java·开发语言
“抚琴”的人2 小时前
C#—【在不同的场景该用哪种线程?】
开发语言·c#·多线程
小道士写程序2 小时前
OSG 和 VTK 在JS仿真中应用的更详细对比分析,包括它们的技术特点、适用场景、优缺点以及如何选择或结合使用
开发语言