电子商务网站建设目标/免费seo网站优化工具

电子商务网站建设目标,免费seo网站优化工具,新建网站的步骤,自己做的网站怎么做客服聊天七、单件模式 单件(Singleton) 模式也称单例模式/单态模式,是一种创建型模式,用于创建只能产生 一个对象实例 的类。该模式比较特殊,其实现代码中没有用到设计模式中经常提起的抽象概念,而是使用了一种比较特殊的语法结构&#x…

七、单件模式

单件(Singleton) 模式也称单例模式/单态模式,是一种创建型模式,用于创建只能产生 一个对象实例 的类。该模式比较特殊,其实现代码中没有用到设计模式中经常提起的抽象概念,而是使用了一种比较特殊的语法结构(私有的构造函数)实现类的定义。
该模式比较好理解,也比较常用,但要设计得好并不容易,有许多细节需要把握,本章将详细探讨。

7.1 单件类的基本概念和实现

在一个软件中,往往存在一些比较特殊的类,希望在整个软件中只存在该类的一个对象(实例)。以闯关打斗类游戏为例,策划要求游戏中有一些配置选项,能够对游戏的声音大小、图像质量等进行配置,为此,要创建一个游戏配置相关的类 GameConfig,代码如下:

// 游戏配置相关类
class GameConfig {// …待增加
};

为了使用该类,需要创建该类相关的对象,于是,可以通过下面的代码创建一个类对象:

GameConfig g_config1;

当然,还可以创建该类的另外一个对象,甚至还可以创建更多的该类对象:

GameConfig g_config2;

但从项目需求来讲,整个游戏中只应该存在一个 GameConfig 类对象(对象可以在栈上创建也可以用 new 在堆上创建),该对象相当于一个全局的 GameConfig 类对象,统管游戏的配置。创建多个 GameConfig 类对象可能会造成混乱或程序逻辑不正确(也可能造成性能问题)。

单件类的设计原则

C++ 软件开发专家 Scott Meyers 曾经说过:“要使接口或者类型易于正确使用,难以错误使用。” 因此,保证类的单一实例化应该由类的设计者实现,而非依赖使用者的自律。

单件类的实现代码

// 游戏配置相关类
class GameConfig {
private:GameConfig() {};GameConfig(const GameConfig& tmpobj);GameConfig& operator=(const GameConfig& tmpobj);~GameConfig() {};public:static GameConfig* getInstance() {if (m_instance == nullptr) {m_instance = new GameConfig();}return m_instance;}private:static GameConfig* m_instance;  // 指向本类对象的指针
};GameConfig* GameConfig::m_instance = nullptr;  // 类外初始化静态成员变量

关键设计点

  1. 私有构造函数:禁止在类外部创建对象(包括栈和堆)。

    GameConfig* g_gc = new GameConfig;  // 非法
    GameConfig gc;                      // 非法
    
  2. 静态工厂方法:通过 getInstance() 创建唯一实例,首次调用时初始化。

  3. 禁止拷贝和赋值

    GameConfig g_gc3(*g_gc);   // 非法(拷贝构造)
    (*g_gc2) = (*g_gc);       // 非法(拷贝赋值)
    
  4. 私有析构函数:禁止外部手动释放对象。

    delete g_gc2;  // 非法
    

7.2 单件类在多线程中可能导致的问题

若多个线程同时调用 getInstance(),可能导致 多次实例化。例如:

  • 线程 1 执行 if (m_instance == nullptr) 后被挂起。
  • 线程 2 同样通过条件判断并创建实例。
  • 线程 1 恢复后再次创建实例,导致两个对象存在。

解决方案 1:加锁

static GameConfig* getInstance() {std::lock_guard<std::mutex> gcguard(my_mutex);  // 加锁if (m_instance == nullptr) {m_instance = new GameConfig();}return m_instance;
}

缺点:每次调用都需加锁,影响性能(仅首次初始化需要保护)。

解决方案 2:双重锁定(Double-Check Locking)

static GameConfig* getInstance() {if (m_instance == nullptr) {  // 第一重检查(无锁)std::lock_guard<std::mutex> lock(m_mutex);  // 加锁if (m_instance == nullptr) {  // 第二重检查(加锁后)m_instance = new GameConfig();}}return m_instance;
}

潜在问题:内存访问重排序可能导致未初始化的对象被使用(需结合 std::atomic 和内存栅栏解决)。

推荐方案

主线程 中提前初始化单件对象,避免多线程竞争:

int main() {GameConfig::getInstance();  // 提前初始化// 创建其他线程...return 0;
}

7.3 饿汉式与懒汉式

单件类的初始化方式分为两种:

饿汉式(Eager Initialization)

特点:程序启动时立即创建实例,线程安全。

class GameConfig {static GameConfig* m_instance = new GameConfig();  // 类外直接初始化
};

缺点:可能提前消耗资源(即使未使用)。

懒汉式(Lazy Initialization)

特点:首次调用 getInstance() 时创建实例,延迟加载。

class GameConfig {static GameConfig* getInstance() {if (m_instance == nullptr) {m_instance = new GameConfig();}return m_instance;}
};

缺点:多线程下需额外处理同步问题。

7.4 单件类对象内存释放问题

单件对象的生命周期通常与程序一致,但可通过以下方式手动释放:

方案 1:手动调用释放函数

class GameConfig {
public:static void freeInstance() {if (m_instance != nullptr) {delete m_instance;m_instance = nullptr;}}
};

方案 2:嵌套类自动释放(Garbo 模式)

class GameConfig {
private:class Garbo {public:~Garbo() {if (GameConfig::m_instance != nullptr) {delete GameConfig::m_instance;GameConfig::m_instance = nullptr;}}};static Garbo garboobj;  // 静态嵌套类对象
};GameConfig::Garbo GameConfig::garboobj;  // 类外初始化

原理:静态对象 garboobj 的析构函数会在程序结束时自动调用,释放单件对象。

7.5 单件类定义、UML 图及另外一种实现方法

单件模式定义

意图:保证一个类仅有一个实例,并提供全局访问点。

UML 图

GameConfig
-_m_instance: GameConfig // 静态成员
+getInstance()
-GameConfig()

另一种实现:返回局部静态变量引用

class GameConfig {
private:GameConfig() {};~GameConfig() {};public:static GameConfig& getInstance() {static GameConfig instance;  // 局部静态变量return instance;}
};

优点

  • 代码简洁,自动处理线程安全(C++11 保证局部静态变量初始化的线程安全)。
  • 实例在首次调用时创建,析构在程序结束时自动执行。

总结

  • 单件类 vs 全局变量:单件类通过封装保证单一实例,全局变量无法阻止多实例。
  • 多线程注意事项:优先在主线程初始化,或使用 C++11 局部静态变量特性。
  • 扩展限制:单件类难以继承,需谨慎设计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/74265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【redis】主从复制:拓扑结构、原理和psync命令解析

文章目录 拓扑一主一从相关问题 一主多从相关问题 树形主从结构相关问题 主从复制原理复制流程 psync 命令命令解析replicatonidoffset总结 运行流程 拓扑 若干个节点之间按照什么样的方式来进行组织连接 一主一从 都可以读&#xff0c;从节点可以帮主节点分担一部分的压力只…

[RoarCTF 2019]Easy Calc-3.23BUUCTF练习day5(2)

[RoarCTF 2019]Easy Calc-3.23BUUCTF练习day5(2) 解题过程 查看源码 发现calc.php页面&#xff0c;访问一下 分析代码 首先获取$_GET[num]的值并赋给变量$str。然后定义了一个黑名单数组$blacklist&#xff0c;包含了一系列被禁止的字符或转义字符&#xff0c;如空格、制表…

阻塞队列:原理、应用及实现

阻塞队列&#xff1a;原理、应用及实现 什么是阻塞队列以生产消费者模型形象地理解阻塞队列阻塞队列实现生产消费者模型模拟实现阻塞队列实现生产消费者模型 什么是阻塞队列 阻塞队列是一种特殊且实用的队列数据结构&#xff0c;它同样遵循 “先进先出” 的原则。与普通队列不…

【开源宝藏】30天学会CSS - DAY5 第五课 脉冲动画

以下是一个完整的渐进式教程&#xff0c;拆解如何用 HTML CSS 构建“Pulsar”水波脉冲动画。通过阅读&#xff0c;你将理解每个核心属性与关键帧如何配合&#xff0c;让一个小圆不断散发动态波纹&#xff0c;并且文字始终停留在圆心。 第 0 步&#xff1a;项目概览 文件结构示…

2060 裁纸刀

2060 裁纸刀 ⭐️难度&#xff1a;简单 &#x1f31f;考点&#xff1a;2022、规律、思维 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N 100010…

python学习笔记--实现简单的爬虫(一)

任务&#xff1a;爬取豆瓣最受欢迎的250个电影的资料 链接&#xff1a;豆瓣电影 Top 250 用浏览器打开后&#xff0c;使用F12或鼠标右键--检查&#xff0c;查看网页的源代码&#xff0c;分析网页结构&#xff0c;如下图所示&#xff1a; 分析后得知&#xff1a; 1.电影名位于…

Cursor+Claude-3.5生成Android app

一、Android Studio下载 https://developer.android.com/studio?hlzh-tw#get-android-studio 等待安装完成 二、新建工程 点击new project 选择Empty Activity 起一个工程名 当弹出这个框时 可以在settings里面选择No proxy 新建好后如下 点击右边模拟器&#xff0c…

Java EE(15)——网络原理——TCP协议解析一

一.确认应答/(确认)序列号 接收方接收到数据后&#xff0c;向发送方返回一个确认信号(ack)&#xff0c;告诉发送方数据被成功接收。ACK报文段只是作为确认使用的&#xff0c;一般来说不携带应用层数据&#xff08;载荷&#xff09;&#xff0c;也就是说只有报头部分。但有可能…

C#单例模式

单例模式 (Singleton),保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问&#xff0c;但它不能防止你实例化对个对象&#xff0c;一个最好的办法就是&#xff0c;让类自身负责保护它的唯一实例。这个类可以保证没…

NO.55十六届蓝桥杯备战|排序|插入|选择|冒泡|堆|快速|归并(C++)

插⼊排序 插⼊排序(Insertion Sort)类似于玩扑克牌插牌过程&#xff0c;每次将⼀个待排序的元素按照其关键字⼤⼩插⼊到前⾯已排好序的序列中&#xff0c;按照该种⽅式将所有元素全部插⼊完成即可 #include <iostream> using namespace std; const int N 1e5 10; …

【Oracle资源损坏类故障】:详细了解坏块

目录 1、物理坏块与逻辑坏块 1.1、物理坏块 1.2、逻辑坏块 2、两个坏块相关的参数 2.1、db_block_checksum 2.2、db_block_checking 3、检测坏块 3.1、告警日志 3.2、RMAN 3.3、ANALYZE 3.4、数据字典 3.5、DBVERIFY 4、修复坏块 4.1、RMAN修复 4.2、DBMS_REPA…

计算机网络高频(二)TCP/IP基础

计算机网络高频(二)TCP/IP基础 1.什么是TCP/IP⭐⭐ TCP/IP是一种网络通信协议,它是互联网中最常用的协议之一。TCP/IP有两个基本的协议:TCP(传输控制协议)和IP(互联网协议)。 TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的协议。它负…

【蓝桥杯】12111暖气冰场(多源BFS 或者 二分)

思路 这题可以用BFS做&#xff0c;也可以用二分来做。 用二分这里只提供一个思路&#xff1a;对时间来二分查找&#xff0c;check函数就是检查在特定的时间 t 0 t_0 t0​内每一个暖气炉的传播距离能否覆盖所有格子。 用BFS做&#xff1a; 由几个点开始向外扩散&#xff0c;知道…

DeepSeek自学手册:《从理论(模型训练)到实践(模型应用)》|73页|附PPT下载方法

导 读INTRODUCTION 今天分享是由ai呀蔡蔡团队带来的DeepSeek自学手册&#xff1a;《从理论&#xff08;模型训练&#xff09;到实践&#xff08;模型应用&#xff09;》&#xff0c;这是一篇关于DeepSeek模型训练、应用场景及替代方案的综合指南文章&#xff0c;主要介绍了Deep…

QT软件匠心开发,塑造卓越设计服务

在当今这个数字化飞速发展的时代&#xff0c;软件已经成为我们生活中不可或缺的一部分。而QT&#xff0c;作为一款跨平台的C图形用户界面应用程序开发框架&#xff0c;凭借其强大的功能和灵活性&#xff0c;在众多软件开发工具中脱颖而出。我们深知&#xff0c;在软件开发领域&…

标贝科技入选2025年市级数据要素市场化配置改革“揭榜挂帅”名单

近日&#xff0c;山东省大数据局、青岛市大数据局公布2025年数据要素市场化配置改革“揭榜挂帅”名单。标贝科技联合崂山区电子政务和大数据中心申报的“政务热线通话录音数据价值挖掘与权益保护”项目成功入选。这一成果不仅彰显了标贝科技在数据领域的创新实力&#xff0c;更…

Flutter TextField 从入门到精通:掌握输入框的完整指南

目录 1. 引言 2. TextField 的基本用法 3. 主要属性 4. 自定义 TextField 样式 4.1 自定义边框与提示文本 4.2 增加前缀/后缀图标 4.3 只允许输入数字 4.4 表单验证系统 4.5 动态样式修改 4.6 防抖搜索&#xff08;Debounce&#xff09; 5. 结论 相关推荐 1. 引言…

MyBatis-Plus 自动填充:优雅实现创建/更新时间自动更新!

目录 一、什么是 MyBatis-Plus 自动填充&#xff1f; &#x1f914;二、自动填充的原理 ⚙️三、实际例子&#xff1a;创建时间和更新时间字段自动填充 ⏰四、注意事项 ⚠️五、总结 &#x1f389; &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢…

arduino R4 SD卡读写测试

使用买来的 st7789LCD 显示器背面就带着一个 tf 卡槽&#xff0c;可以直接连接 tf 卡。使用 Sdfat 库就可以实现对 sd 卡的读写操作。这里尝试测试 sd 卡的读写功能。 LCD 显示器的初始化 //定义LCD的对象 Adafruit_ST7789 tft Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);tf…

【武汉·4月11日】Parasoft联合光庭信息研讨会|邀您共探AI赋能新机遇

Parasoft联合光庭信息Workshop邀您共探AI赋能新机遇 AI浪潮已至&#xff0c;你准备好了吗&#xff1f; 在智能网联汽车飞速发展的今天&#xff0c;AI技术正以前所未有的速度重塑行业生态。如何把握AI机遇&#xff0c;赋能企业创新&#xff1f; 4月11日&#xff0c;自动化软件…