单例模式(上)

qt案例:

 // 注册多个数据管理服务为单例类型,使它们可以在 QML 中被访问。
    qmlRegisterSingletonType<MainDataManage>("MainDataManage", 1, 0, "MinIns", MainDataManageGetInsTance);

这种注册方式非常适合在 QML 中集成复杂的后端逻辑,使得前端界面可以直接调用后端逻辑的单例实例进行数据处理或业务逻辑运算。

注册 MainDataManage 类型为单例类型。
在 QML 中,可以通过 MinIns 访问这个单例。
使用 MainDataManageGetInsTance 函数来获取 MainDataManage 的实例。
每个注册函数都通过指定一个类型、命名空间、版本号0和一个标识符MinIns,以及一个获取实例的函数。这允许在 QML 环境中访问这些 C++ 单例类的实例。
  • 类型 (Type): MainDataManage
    这是要注册为单例的 C++ 类的名称。
  • 命名空间 (Namespace): “MainDataManage”
    在 QML 中使用这个命名空间来访问单例。通常来说,这个命名空间可以看作是在 QML 中的一个标识符,不过在这里它也作为模块的名称,可能与类型名称相同。
  • 版本号 (Major and Minor Version): 1, 0
    这是注册类型的主版本号和次版本号。主版本号是 1,次版本号是 0。这对于管理 QML 中类型的版本非常有用,尤其是在API有更改时。
  • 标识符 (Identifier): “MinIns”
    这是在 QML 中引用此单例实例的标识符。通过这个标识符,QML 代码可以访问和实例化这个单例类。

功能:

这行代码的功能是在 QML 中注册一个单例服务,允许 QML 直接访问和操作 MainDataManage 类的实例,而这个实例是通过 MainDataManageGetInsTance 函数来创建和获取的。这种方式常用于将复杂的逻辑或数据管理从 C++ 后端暴露给 QML 前端。

MainDataManage 类的结构

#include <QObject>

// 假设 MainDataManage 是从 QObject 继承的,这在 Qt 中很常见,特别是需要信号和槽机制时。
class MainDataManage : public QObject {
    Q_OBJECT

private:
    // 私有的静态指针,指向类的唯一实例
    static MainDataManage* instance;

    // 私有构造函数,确保不会从外部创建类的实例
    MainDataManage() {}

public:
    // 删除拷贝构造函数和赋值运算符,确保类的唯一性
    MainDataManage(const MainDataManage&) = delete;
    void operator=(const MainDataManage&) = delete;

    // 公有的静态方法,用于获取类的单例实例
    static MainDataManage* getInsTance() {
        if (instance == nullptr) {
            instance = new MainDataManage();
        }
        return instance;
    }

    // 示例方法,表示类的功能
    void loadData() {
        // 加载数据的逻辑
    }

    // 示例方法,表示类的功能
    void saveData() {
        // 保存数据的逻辑
    }
};

// 初始化静态成员变量
MainDataManage* MainDataManage::instance = nullptr;

C++中类的实例化

在编程中,一个类的实例是根据类定义创建的具体对象。类提供了对象的蓝图,而实例则是根据这个蓝图构建的实际实体,包含了类定义的属性和方法。实例化是创建这些对象的过程,每个实例都拥有类定义的所有特征和行为。

以之前提供的 MainDataManage 类为例,我们可以创建其实例(在这种情况下,由于采用单例模式,我们将只能获取这个单例实例)。这里是如何获取 MainDataManage 类的单例实例的示例代码:

int main() {
    // 获取 MainDataManage 类的单例实例
    MainDataManage* manager = MainDataManage::getInsTance();

    // 使用实例的方法
    manager->loadData();
    manager->saveData();

    return 0;
}

通过这样的实例,你可以在程序的任何地方访问和操作与 MainDataManage 相关的数据和功能,而不需要重新创建类的多个实例。这种模式在需要控制资源访问或保持全局状态一致时特别有用。

QML中调用MinIns

  1. 导入模块
    首先,您需要确保 QML 文件知道从哪里可以找到这个单例。因为它是通过特定的模块名和版本号注册的,所以您需要在 QML 文件顶部导入对应的模块。假设 MainDataManage 被注册为版本 1.0,在 QML 文件的开始,您应该添加如下导入语句:
import MainDataManage 1.0
  1. 使用单例
    一旦导入了正确的模块,就可以直接使用在 C++ 中定义的单例名 “MinIns” 来访问所有公开的方法和属性。这可以在任何 QML 的上下文中直接使用,例如在函数中或绑定表达式中。

示例 QML 使用
假设 MainDataManage 类有一个方法 loadData() 和一个属性 dataLoaded。在 QML 中,您可以这样使用它们:

import QtQuick 2.12
import MainDataManage 1.0 // 根据实际的模块名和版本号进行修改

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: "Singleton Example"

    Component.onCompleted: {
        MinIns.loadData()  // 在窗口组件加载完成后调用 loadData 方法
    }

    Text {
        id: statusText
        text: "Loading..."
        anchors.centerIn: parent

        // 假设 MainDataManage 有个信号 dataLoaded() 表示数据加载完成
        Connections {
            target: MinIns
            onDataLoaded: statusText.text = "Data loaded successfully!"
        }
    }
}

说明
导入模块:import MainDataManage 1.0 告诉 QML 解释器从哪里找到 MainDataManage 模块,这个模块包含了您的单例。
访问单例:通过单例的引用 “MinIns”,可以直接调用其方法 loadData() 或访问属性 dataLoaded。
使用场景:在 Component.onCompleted 事件中调用 loadData() 方法来初始化数据加载。文本组件则显示当前的加载状态,这是通过绑定到 dataLoaded 属性实现的。
通过这种方式,QML 代码可以直接与后端 C++ 代码交互,实现复杂的逻辑和状态管理,同时保持前端的轻量级和响应性。这也展示了 QML 和 C++ 在 Qt 应用程序中如何协同工作。

补充说明 target: MinIns

import QtQuick 2.12
import MainDataManage 1.0  // 确保导入的是正确的模块名称和版本

Rectangle {
    width: 400
    height: 400

    // 使用 Connections 元素来监听 MinIns 发出的信号
    Connections {
        target: MinIns  // 指定 MinIns 为信号源

        // 假设 MainDataManage 类定义了一个 signalDataLoaded() 信号
        onDataLoaded: {
            console.log("Data has been successfully loaded.")
            // 在此执行其他相关的UI更新或逻辑处理
        }
    }

    Component.onCompleted: {
        MinIns.loadData()  // 触发数据加载
    }
}

C++单例模式


#include <iostream>

class Singleton {
public:
    // 获取单例实例的静态方法
    static Singleton& getInstance() {
        static Singleton instance; // 在首次调用时初始化,保证只有一个实例
        return instance;
    }

    // 禁用拷贝构造函数和赋值运算符,确保只有一个实例
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    // 示例方法
    void doSomething() {
        std::cout << "Singleton is doing something." << std::endl;
    }

private:
    // 私有构造函数,禁止外部实例化
    Singleton() {
        std::cout << "Singleton instance created." << std::endl;
    }

    // 私有析构函数,禁止外部销毁实例
    ~Singleton() {
        std::cout << "Singleton instance destroyed." << std::endl;
    }
};

int main() {
    // 获取单例实例
    Singleton& singleton = Singleton::getInstance();
    singleton.doSomething();

    // 尝试创建多个实例(编译时会报错)
    // Singleton anotherInstance; // 编译错误:无法访问 Singleton 的构造函数
    // Singleton* ptr = new Singleton(); // 编译错误:无法访问 Singleton 的构造函数

    return 0;
}

在这里插入图片描述

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值