【QA】工厂模式在Qt有哪些应用?
#设计模式 #Qt
在原生 Qt 框架的设计里,工厂模式被广泛应用,它将对象的创建和使用进行分离,增强了代码的可维护性与可扩展性。以下是一些典型的应用场景:
1. QAbstractItemModel
及其子类
在 Qt 的模型 - 视图架构中,QAbstractItemModel
是抽象基类,用于提供数据给视图组件(如 QListView
、QTreeView
、QTableView
等)。不同类型的数据需要不同的具体模型类来实现,这里就运用了工厂模式的思想。
应用方式
- 抽象模型类:
QAbstractItemModel
定义了一系列纯虚函数,像rowCount
、columnCount
、data
等,这些函数是所有具体模型类必须实现的接口。 - 具体模型类:例如
QStandardItemModel
、QSqlTableModel
等,它们继承自QAbstractItemModel
,并实现了具体的数据管理和访问逻辑。在实际使用时,开发者可以根据需求选择合适的具体模型类来创建模型对象。
示例代码
#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 使用 QStandardItemModel 工厂创建一个具体的模型对象
QStandardItemModel model(4, 2);
model.setHorizontalHeaderLabels({"Name", "Age"});
model.setItem(0, 0, new QStandardItem("Alice"));
model.setItem(0, 1, new QStandardItem("25"));
QTableView tableView;
tableView.setModel(&model);
tableView.show();
return a.exec();
}
2. QStyle
及其子类
QStyle
类为 Qt 应用程序提供了界面风格的抽象接口,不同的平台和用户需求可以对应不同的具体风格类。
应用方式
- 抽象风格类:
QStyle
定义了一系列用于绘制界面元素的纯虚函数,如drawControl
、drawPrimitive
等。 - 具体风格类:Qt 提供了多种具体风格类,如
QWindowsStyle
、QMacStyle
、QFusionStyle
等。这些类继承自QStyle
,并实现了特定平台或风格的绘制逻辑。可以通过QApplication::setStyle
方法来选择合适的具体风格类创建风格对象。
示例代码
#include <QApplication>
#include <QPushButton>
#include <QStyleFactory>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 使用 QStyleFactory 工厂创建一个具体的风格对象
QApplication::setStyle(QStyleFactory::create("Fusion"));
QPushButton button("Click me");
button.show();
return a.exec();
}
3. QImageIOHandler
及其子类
在处理图像输入输出时,QImageIOHandler
是抽象基类,用于支持不同格式的图像文件。
应用方式
- 抽象处理类:
QImageIOHandler
定义了一系列用于读取和写入图像的纯虚函数,如canRead
、read
、write
等。 - 具体处理类:Qt 为不同的图像格式提供了具体的处理类,如
QJpegHandler
、QPngHandler
等。这些类继承自QImageIOHandler
,并实现了特定图像格式的读写逻辑。QImageReader
和QImageWriter
类在内部使用工厂模式来根据文件格式选择合适的处理类。
示例代码
#include <QApplication>
#include <QImageReader>
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QImageReader reader("example.jpg");
QImage image = reader.read();
QLabel label;
label.setPixmap(QPixmap::fromImage(image));
QVBoxLayout layout;
layout.addWidget(&label);
QWidget window;
window.setLayout(&layout);
window.show();
return a.exec();
}
4. QPluginLoader
与插件系统
Qt 的插件系统允许开发者动态加载和使用插件,其中也运用了工厂模式的思想。
应用方式
- 抽象插件接口:开发者定义一个抽象的插件接口类,包含插件需要实现的纯虚函数。
- 具体插件类:插件开发者实现具体的插件类,继承自抽象插件接口,并实现相应的功能。
- 插件加载器:
QPluginLoader
类用于加载插件,并通过插件的元对象系统来创建具体的插件对象。
示例代码
// 抽象插件接口
#include <QObject>
class MyPluginInterface {
public:
virtual ~MyPluginInterface() {}
virtual void doSomething() = 0;
};
#define MyPluginInterface_iid "com.example.MyPluginInterface"
Q_DECLARE_INTERFACE(MyPluginInterface, MyPluginInterface_iid)
// 具体插件类
#include <QObject>
#include "myplugininterface.h"
class MyPlugin : public QObject, public MyPluginInterface {
Q_OBJECT
Q_INTERFACES(MyPluginInterface)
public:
void doSomething() override {
// 实现具体功能
}
};
// 主程序加载插件
#include <QApplication>
#include <QPluginLoader>
#include "myplugininterface.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPluginLoader loader("myplugin.dll");
QObject *plugin = loader.instance();
if (plugin) {
MyPluginInterface *myPlugin = qobject_cast<MyPluginInterface*>(plugin);
if (myPlugin) {
myPlugin->doSomething();
}
}
return a.exec();
}
在上述这些 Qt 原生设计中,工厂模式使得代码结构更加清晰,便于扩展和维护。通过将对象的创建逻辑封装在具体的工厂类或抽象基类的子类中,开发者可以根据不同的需求灵活选择合适的对象创建方式。