首页 > 其他分享 >单例模式

单例模式

时间:2023-04-10 20:33:56浏览次数:39  
标签:pInstance 函数 对象 成员 创建对象 模式 单例 类外

单例模式

单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。即:类在内存中只能存在一个示例对象

设计思路:

创建的对象肯定是要存入内存的,也就是用户态的那片空间(栈、堆、读写段、只读段),如果直接将类对象的创建放在类的外面,无论放在哪块区域都是行不通的。故需要强制不能在类外创建对象,而对象的创建都需要构造函数,对象的销毁都需要析构函数。这样,我们可以将构造函数和析构函数设置为私有的,强制用户不可以在类外创建对象。于是,我们需要在类的里面创建对象,而在堆上创建对象是我们程序员最可控的区域,故我们选择在堆上创建对象。

使用场景:全局唯一的对象,网页库、日志记录器

#include <stdio.h>
#include <iostream>

using std::cout;
using std::cin;
using std::endl;

class Singleton
{
public:
    // 将对象的创建放在函数里面
    // 在类的外面访问成员函数除了使用对象加点的方式或者指针的方式(而此时的目的就是创建对象,此时是没有对象的,这两种方法行不通)
    // 还可以将成员函数用static修饰,这样在类外可以通过类名加作用域限定符的形式直接调用来创建对象(静态成员函数的特色)
    static Singleton* getInstance()
    {
        // 为保证 只能有一个对象的需求 需要一个指针来接收堆对象的指针
        
        // Singleton* _pInstance;// 这样每次进来_pInstance同样为空,每次还是会进入if语句,起不到效果,因此需要将其设置为全局变量
        // 但全局变量要求是能不使用就不要使用的,故将其设置为类里的一个数据成员
        if(_pInstance == nullptr)
        {
            _pInstance = new Singleton();// 在类中创建堆对象
        }
        return _pInstance;
    }

    // 同样,为了能够在类外用类名加作用域限定符的方式去释放对象,将该函数设置为静态成员函数
    static void destroy()
    {
        // 防止double free
        if(_pInstance != nullptr)
        {
            delete _pInstance;
            _pInstance = nullptr;
        }
    }
private:
    Singleton()
    {
        cout << "Singleton()" << endl;
    }
    // 同样,析构函数需要放在private区域,防止在类外使用时,出现double free的问题
    ~Singleton()
    {
        cout << "~Singleton()" << endl;
    }
private:
    // 静态成员函数只能访问静态数据成员,故需要将其用static修饰
    static Singleton* _pInstance;   
};

// 静态数据成员必须在读写区进行初始化
Singleton* Singleton::_pInstance = nullptr;

int main()
{

    Singleton* ps1 =  Singleton::getInstance();
    Singleton* ps2 =  Singleton::getInstance();
    
    printf("ps1 = %p\n",ps1);
    printf("ps2 = %p\n",ps2);

    Singleton::destroy();
    Singleton::destroy();
    Singleton::destroy();
    Singleton::destroy();

    // delete ps1;  // 将析构函数设置为private时,这样使用会报错

    return 0;
}

运行结果:

几个点:

为什么只能在类里面创建对象?

答:如果允许在类外创建对象,不论在那片内存区域创建对象都无法满足一个类只能创建一个实例对象的需求。

为什么getInstance()函数要设计为静态成员函数?

答:因为经分析,不可以在类的外面创建对象,而在类外访问类的成员可以通过对象加点的或者指针的形式去访问,但是此时对象并没有创建出来,这两种方式都是行不通的。所以,我们可以将getInstance()设计为静态的成员函数,这样可以直接在类外通过作用域限定符加上类名的方式调用此函数,进而创建唯一的对象。

为什么要单独设计destroy()这个函数来释放对象?

答:因为析构函数已经被设置为私有成员了,在类外是无法调用的。并且同样为了能在类外直接使用,我们也需要将其设计为静态成员函数。

为什么静态数据成员_pInstance需要用static修饰?

答:因为静态成员函数只能访问静态的数据成员。

标签:pInstance,函数,对象,成员,创建对象,模式,单例,类外
From: https://www.cnblogs.com/MyXjil/p/17304203.html

相关文章

  • KMP算法(串的模式匹配算法)(未完待续......)
    KMP算法的实现1.基本原理  在暴力破解算法(BF算法)中,模式串需要一个一个来跟主串进行对比,若有一个不相同,则主串前进一位,继续从头开始进行比较,这样比较的最坏时间复杂度为O(mn),例:‘aaaaaaaaab’和‘aaab’,需要比较到最后一个才能成功,效率太过低下。  KMP算法的原理是,找到模式串......
  • VMware网络连接模式
    VMware网络连接模式一、桥接模式1.介绍相当于虚拟机的网卡和宿主机的物理网卡连接到虚拟机所提供的VMnet0虚拟交换机上2.作用虚拟机、宿主机均可访问外网虚拟机、宿主机之间可通信3.操作关闭宿主机和虚拟机防火墙Windows:控制面板-->系统和安全-->WindowsDefender......
  • 【享元设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
    简介享元模式(FlyweightPattern),是一种结构型设计模式。主要用于减少创建对象的数量,以减少内存占用和提高性能。它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。当程序需要生成数量巨大的相似对象时,可能对内存有......
  • AOP底层原理-装饰模式(静态代理)
    原始方法:静态代理的方法:   测试:  ......
  • Docker的网络模式
    1、Docker网络实现原理(1)Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器......
  • 详解事务模式和Lua脚本,带你吃透Redis 事务
    摘要:Redis事务包含两种模式:事务模式和Lua脚本。本文分享自华为云社区《一文讲透Redis事务》,作者:勇哥java实战分享。准确的讲,Redis事务包含两种模式:事务模式和Lua脚本。先说结论:Redis的事务模式具备如下特点:保证隔离性;无法保证持久性;具备了一定的原子性,但不支持回滚;一致性的概念......
  • 详解事务模式和Lua脚本,带你吃透Redis 事务
    摘要:Redis事务包含两种模式:事务模式和Lua脚本。本文分享自华为云社区《一文讲透Redis事务》,作者:勇哥java实战分享。准确的讲,Redis事务包含两种模式:事务模式和Lua脚本。先说结论:Redis的事务模式具备如下特点:保证隔离性;无法保证持久性;具备了一定的原子性,但不支持回滚;一......
  • 【设计模式25】中介者模式
    基本概念具体案例#include<iostream>#include<vector>#include<string>#include<algorithm>#include<crtdbg.h>#include<unordered_map>usingnamespacestd;classCountry;//联合国机构classUniteNations{public: UniteNations()......
  • 【设计模式9】原型模式
    脑图展开一般模型具体案例(Qt,C++)定义相关类,实现个人简历的初始化和拷贝工作,其中简历的数据成员包括:姓名、性别、年龄、任职时段、任职公司,以及用于观察浅拷贝的引用(指针)成员;classICloneable{public:ICloneable();virtualICloneable*Clone()=0;//抽象的Clone方......
  • 【设计模式7】代理模式
    基本概念(1)代理模型:为其他对象提供一种代理以控制这个对象的访问。(2)代理模式的适用场景:远程代理,也就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实;虚拟代理,根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象,从而......