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

相关推荐
我狸才不是赔钱货1 小时前
Python的“环境之殇”:从Venv到Conda的终极抉择
开发语言·python·conda
努力进修1 小时前
Rust 语言入门基础教程:从环境搭建到 Cargo 工具链
开发语言·后端·rust
杯莫停丶6 小时前
设计模式之:模板模式
开发语言·设计模式
开发者小天6 小时前
调整为 dart-sass 支持的语法,将深度选择器/deep/调整为::v-deep
开发语言·前端·javascript·vue.js·uni-app·sass·1024程序员节
老猿讲编程7 小时前
C++中的奇异递归模板模式CRTP
开发语言·c++
汤姆yu9 小时前
基于python的化妆品销售分析系统
开发语言·python·化妆品销售分析
ScilogyHunter9 小时前
C语言标准库完全指南
c语言·开发语言
sali-tec9 小时前
C# 基于halcon的视觉工作流-章52-生成标定板
开发语言·图像处理·人工智能·算法·计算机视觉
应茶茶9 小时前
C++11 核心新特性:从语法重构到工程化实践
java·开发语言·c++
程子的小段10 小时前
C 语言实例 - 字符串复制
c语言·开发语言