QT之单例模式

一.概述

1.什么是单例模式

单例模式(Singleton Pattern)是一种设计模式,用于确保一个类只有一个实例,并提供全局访问点以访问该实例。

在应用程序的整个生命周期内,只能创建一个特定类的对象。

单例模式常用于需要共享资源或控制共享某些资源的情况,以确保资源的一致性和有效管理。

例如一般一个程序中只有一个日志输出实例,一个系统中只有一个数据库连接实例,这时候用单例模式非常合适。

2.单例模式通常包括要素

私有构造函数:单例类通常将其构造函数设为私有,以防止外部代码直接实例化类的对象。

静态成员变量:单例类通常包含一个私有的静态成员变量,用于存储类的唯一实例。

静态成员函数:单例类通常包含一个公共的静态成员函数,通常命名为 getInstance() 或 Instance(),用于获取单例类的实例。

说明:用getInstance或者Instance没有区别,但从直观理解上用getInstance更好一点

延迟初始化:在首次调用 getInstance() 方法时才创建类的唯一实例,以延迟初始化。

线程安全性:如果在多线程环境中使用单例模式,需要确保线程安全性,以防止多个线程同时创建实例。通常可以使用互斥锁等机制来实现线程安全性。

3.单例模式的 点和缺点

优点:

提供全局访问点,方便在应用程序的不同部分共享对象。

确保只有一个实例存在,节省资源。

提供对单一资源或配置的集中管理。

支持懒加载,只在需要时创建实例。

缺点:

可能导致全局状态,增加了代码的耦合性。

在某些情况下可能会引入单点故障。

难以进行单元测试,因为单例对象难以模拟或替代。

二.代码实现

1.简单的单例实现

(1)test.h

#ifndef MYWIDGET_H

#define MYWIDGET_H

#include <QWidget>

#include <QString>

class MyWidget : public QWidget {

Q_OBJECT

public:

static MyWidget* getInstance();

void updateData(const QString& data);

private:

MyWidget(QWidget* parent = nullptr);

static MyWidget* instance;

};

#endif // MYWIDGET_H

(2)test.cpp

#include "test.h"

#include <QDebug>

MyWidget* MyWidget::instance = nullptr;

MyWidget* MyWidget::getInstance() {

if (!instance) {

instance = new MyWidget();

}

return instance;

}

MyWidget::MyWidget(QWidget* parent) : QWidget(parent) {

// 初始化界面部件

}

void MyWidget::updateData(const QString& data)

{

qDebug()<<"display:"<<data;

}

(3)调用

#include "test.h"

MyWidget* myWidget = MyWidget::getInstance();

myWidget->updateData("Some data to display");

//或者

MyWidget::getInstance()->updateData("Some data to display");

2.线程安全的单例示例

(1)test.h

#ifndef MYWIDGET_H

#define MYWIDGET_H

#include <QWidget>

#include <QString>

class MyWidget : public QWidget {

Q_OBJECT

public:

static MyWidget* getInstance();

void updateData(const QString& data);

private:

MyWidget(QWidget* parent = nullptr);

static QScopedPointer<MyWidget> self;

};

#endif // MYWIDGET_H

(2)test.cpp

#include "test.h"

#include <QDebug>

#include "qmutex.h"

QScopedPointer<MyWidget> MyWidget::self;

MyWidget *MyWidget::getInstance()

{

if (self.isNull()) {

static QMutex mutex;

QMutexLocker locker(&mutex);

if (self.isNull()) {

self.reset(new MyWidget);

}

}

return self.data();

}

MyWidget::MyWidget(QWidget* parent) : QWidget(parent) {

// 初始化界面部件

}

void MyWidget::updateData(const QString& data)

{

qDebug()<<"display:"<<data;

}

(3)调用

#include "test.h"

MyWidget::getInstance()->updateData("Some data to display");

相关推荐
淘矿人14 分钟前
DeepSeek V4对决Claude 4.8:AI模型终极横评
java·开发语言·人工智能·python·sql·php·pygame
走好每一步33 分钟前
1、VTK+QT + cmake编程 三维圆柱体
qt·vtk
skywalk816341 分钟前
你希望的「多路捕获」语法是哪种形式?具体而言,「捕获 类型为 e」指的是什么?
开发语言·编程
两年半的个人练习生^_^1 小时前
JMM 进阶:彻底理解 volatile 实现原理
java·开发语言
晚风吹红霞1 小时前
C++模板进阶:非类型参数、特化、分离编译与优缺点解析
开发语言·c++
小小龙学IT1 小时前
Go语言后端开发入门指南
开发语言·后端·golang
不会C语言的男孩1 小时前
C++ Primer 第8章:IO 库
开发语言·c++
兰令水1 小时前
leecodecode【层序遍历】【2026.6.3打卡-java版本】
java·开发语言
Halo_tjn1 小时前
反射与设计模式2
java·开发语言·算法
kaoa0001 小时前
Linux入门攻坚——79、XEN虚拟化-2
linux·运维·开发语言