首页 > 其他分享 >单例模式(正式)

单例模式(正式)

时间:2023-09-24 16:45:19浏览次数:26  
标签:Singleton 正式 对象 模式 instance 实例 static 单例

当需要严格控制一个类在全局只有唯一一个实例,并且可以随时调用它的时候,就可以使用单例模式。

单例模式可以以实例化时间分为懒汉式和饿汉式、以C实现方式分为C++98的实现以及C++11的实现。

懒汉式

c++11
class Singleton {
 public:
    static Singleton* getInstance() {
	    if(m_instance == nullptr) {
		    m_instance = new Singleton();
	    }
	    return m_instance;
    }
 private:
    Singleton(){}
    ~Singleton(){}
    static Signeton* m_instance;
};
class Singleton {
 public:
    static Singleton& GetInstance() {
	    static Singleton instance;
	    return instance;
    }
 private:
    Singleton() = default;
    ~Singleton() {}
};

也就是说, Singleton 通过将构造函数私有化实现了对实例化的控制,只有通过调用 getInstance() 才能生成并获得这唯一一个实例。

同时,这是一个懒汉式的实现,只有在调用 getInstance() 一次过后才有一个 Singleton 被实例化。

代码注解:

  • 这段代码使用指针的目的是为了延迟单例类的实例化,并在需要时动态地创建和访问实例对象。

  • 通过使用 new 运算符创建一个 Singleton 类的实例对象,并将其赋值给静态成员 m_instance,以确保只有一个实例对象被创建。需要注意的是,静态成员 m_instance 存储的是实例对象的地址,而不是对象本身。因此,在使用时需要通过解引用操作符 * 来获取实际的对象。

静态成员变量定义只能在源文件:

    重复编译 减少初始化操作

静态成员:

  • 如果把类的成员声明为静态的,就可以把它与类的对象独立开来(静态成员不属于对象)

  • 用 static 关键字把类的成员变量声明为静态,表示它在程序中(不仅是对象)是共享的。

  • 静态成员只有一份,在全局存储区

  • 静态成员使用类名加范围解析运算符 :: 就可以访问,不需要创建对象。

饿汉式

// in 'Singleton.h'
class Singleton {
 public:
    static Singleton& GetInstance {
	    return instance;
    }
 private:
    Singleton() = default;
    ~Singleton() {}
    static Singleton instance;
};

// in 'Singleton.cpp'
Singleton Singleton::instance;

代码讲解

  • GetInstance() 方法返回一个 Singleton 对象的引用。

  • 在 C++11 中,使用局部静态变量可以确保只有一个实例对象被创建。在这段代码中,instance 是一个局部静态变量,它在第一次调用 GetInstance() 方法时被创建,而在后续的调用中会直接返回已经存在的实例对象。

  • 构造函数 Singleton() 和析构函数 ~Singleton() 都使用 default 关键字进行了默认定义,即使用编译器生成的默认实现。它们被声明为 private,防止在类外部直接创建和销毁对象。

  • 通过这种实现方式,可以简洁地实现只有一个实例对象被创建,并且可以通过引用来访问该对象。

懒汉模式和恶汉模式是两种单例模式实现方式的区别:

懒汉模式:在首次使用时才创建实例对象,延迟实例化,可能存在线程安全问题。

恶汉模式:在类加载时就创建实例对象,立即实例化,不存在线程安全问题。

懒汉模式节省内存空间,但可能引入延迟和线程安全问题;恶汉模式简单直接,但可能浪费部分内存空间。选择取决于内存占用、延迟和线程安全需求。

竞争的场景:

两个线程在调用结构的过程中,如判断是否空指针的时候,一个在判断为空指针后准备创建对象,另一个在此时也判断为空的指针
//Singleton.h
/* C++98 */
class Singleton11{
 public:
    static Singleton98* getInstance() {
	    if(m_instance == nullptr) {
		    std::lock_guard<std::mutex> lock(m_mutex);
		    if(m_instance == nullptr) {
			    m_instance = new Singleton();
		    }
	    }
	    return m_instance;
    }
 private:
	 //...
}
/* C++11 */
class Singleton11{
 public:
    static Singleton11& getInstance() {
	    std::call_once(m_flag, []() {
		    m_instance.reset(new Singleton11);
	    });
    }
 private:
	 //...
	 static std::mutex m_mutex;
}

//Singleton.cpp
/* C++98 */
Singleton98* Singleton98::m_instance = nullptr;
std::mutex Singleton98::m_mutex;
/* C++11 */
std::unique_ptr<Singleton11> Singleton11::m_instance;
std::once_flag Singleton11::m_flag;

问题:image

  • 多线程需要考虑多次new的问题,需要使用线程同步如互斥锁

  • 忘记delete!

用处

资源共享:当多个对象需要共享同一个资源时,可以使用单例模式来管理该资源。例如,数据库连接池、线程池等。
配置信息:单例模式可以用于管理全局的配置信息,确保在整个应用程序中只有一个配置对象,方便访问和修改配置。
日志记录器:在日志记录中,使用单例模式可以确保只有一个日志记录器实例,所有的日志信息都在同一个地方进行记录,并且可以方便地访问和控制日志记录器。

标签:Singleton,正式,对象,模式,instance,实例,static,单例
From: https://www.cnblogs.com/Gal0721/p/17726168.html

相关文章

  • 建造者模式
    建造者模式动机将一个复杂对象的创建过程及其表示分离,同一个创建过程可以创建不同的表示当需要创建一个包含多个部分或配置选项的复杂对象,并且需要将构建过程与表示分离时,建造者模式很有用帮助你灵活地构建不同配置的对象,同时保持构建过程的清晰性和可维护性经典Builder模......
  • 工厂模式(正式)
    抽象工厂模式及示例模式的动机提供一种接口,用于创建一系列相关或相互依赖的对象抽象工厂模式通过引入抽象工厂接口,允许客户端代码通过工厂接口创建产品,而不需要关心具体的产品类;使得客户端代码可以与特定产品的具体类解耦,实现了抽象和实现的分离模式的实现抽象的......
  • Kibana数据索引模式设计策略案例
    前言Kibana是一个非常流行的数据可视化工具,它可以帮助我们快速地对数据进行分析和展示。在使用Kibana的过程中,数据索引模式的设计非常重要,它直接影响到我们对数据的查询和分析效率。本文将介绍一些Kibana数据索引模式设计的策略案例,希望能够帮助大家更好地使用Kibana。策略一:尽量......
  • 代理模式
    工作场景:让用户根据接口查询系统各资源占用率优化用户性能传统代码:传统代码//main.cpp#include<iostream>#include"ServerInfoGetter.h"#include<chrono>#include<thread>intmain(){ ServerInfoGettergetter; ServerInfoinfo=getter.getInfo(); whil......
  • Redis搭建哨兵模式架构
    使用Docker安装因为配置太复杂,所以这里我们使用dockercompose来一键部署不使用内部网络搭建编写redis主从docker-compose.ymlversion:'3'services:master:image:rediscontainer_name:redis-masterrestart:alwayscommand:redis-server--requi......
  • Remix 2.0 正式发布,现代化全栈Web框架!
    9月16日,全栈Web框架Remix正式发布了2.0版本,Remix团队在发布1.0版本后经过近2年的持续努力,发布了19个次要版本、100多个补丁版本,并解决了数千个问题和拉取请求,终于迎来了第二个主要版本!Remix具有以下特性:追求速度、用户体验(UX),支持任何SSR/SSG等基于We......
  • 工厂模式
    工作场景:编写一个给用户发送短信的程序传统写法#include<stdio.h>#include<string>enumNotifMessageType{WUDI,FEITIAN};classNotifMessage{public:intsendMessage(longlonguserId,std::string&msg,NotifMessageTypetype){s......
  • 模式
    模式2.7.1.1、模式的定义定义模式实际上定义了一个命名空间,在这个空间中可以定义该模式包含的数据库对象,例如基本表、视图、索引等。在CREATESCHEMA中可以接受CREATETABLE,CREATEVIEW和GRANT子句。CREATESCHEMA<模式名>AUTHORIZATION<用户名>[<表定义子句>|<视图定义子句>|<......
  • Next.js 13.5 正式发布,速度大幅提升!
    9月19日,Next.js13.5正式发布,该版本通过以下方式提高了本地开发性能和可靠性:本地服务器启动速度提高22%:使用App和PagesRouter可以更快地进行迭代HMR(快速刷新)速度提高29%:在保存更改时进行更快的迭代内存使用量减少40%:在运行nextstart时测量优化的包导入:使用......
  • 央视新闻“潮涌号”直播车:远程星瀚H、远程超级VAN正式亮相
    9月23日,央视新闻推出《潮涌杭州亚运来了》大型融媒体节目,远程星瀚H、远程超级VAN作为央视潮涌号移动演播室用车、央视潮涌号金牌演播室用车正式亮相,并将驶向各大赛区、场馆,在行进中带领观众感受亚运脉搏。亚运赛事期间,远程星瀚H、远程超级VAN将为央视新闻提供全方位保障服务,以领先......