单例模式

2021-04-23  本文已影响0人  小幸运Q

保证一个类仅可以有一个实例化对象,并且提供一个可以访问它的全局接口。实现单例模式必须注意以下几点:

  1. 单例类只能由一个实例化对象。
  2. 单例类必须自己提供一个实例化对象。
  3. 单例类必须提供一个可以访问唯一实例化对象的接口。

单例模式分为懒汉和饿汉两种实现方式。


懒汉模式

不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化一个对象。在访问量较小,甚至可能不会去访问的情况下,采用懒汉实现,这是以时间换空间。

image.png

非线程安全版:

/*
* 关键代码:构造函数是私有的,不能通过赋值运算,拷贝构造等方式实例化对象。
*/

​#include<iostream>
using namespace std;
//懒汉式一般实现:非线程安全,getInstance返回的实例指针需要delete
class Singleton
{
public:
    static Singleton* getInstance();
    ~Singleton(){}
​
private:
    Singleton(){}                                        //构造函数私有
    Singleton(const Singleton& obj) = delete;            //明确拒绝
    Singleton& operator=(const Singleton& obj) = delete; //明确拒绝

    static Singleton* m_pSingleton;
};
​
Singleton* Singleton::m_pSingleton = NULL;
​
// 第一次访问getInstance才会new,并且要在private函数里
Singleton* Singleton::getInstance()
{
    if(m_pSingleton == NULL)
    {
        m_pSingleton = new Singleton;
    }
    return m_pSingleton;
}

int main(){
    // Singleton* s=new Singleton();  
    // 构造函数私有无法调用
    Singleton* s=Singleton::getInstance();
    s->print();
}

线程安全版:(双重检查)
也可以先加锁然后检查一次,但是先检查可以避免已分配情况下的加锁操作,减小开销。

std::mutex mt;

class Singleton
{
public:
    static Singleton* getInstance();
private:
    Singleton(){}                                    //构造函数私有
    Singleton(const Singleton&) = delete;            //明确拒绝
    Singleton& operator=(const Singleton&) = delete; //明确拒绝

    static Singleton* m_pSingleton;

};
Singleton* Singleton::m_pSingleton = NULL;

Singleton* Singleton::getInstance()
{
    if(m_pSingleton == NULL)
    {
        mt.lock();
        if(m_pSingleton == NULL)
        {
            m_pSingleton = new Singleton();
        }
        mt.unlock();
    }
    return m_pSingleton;
}

饿汉模式

饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

//饿汉式:线程安全,注意一定要在合适的地方去delete它
class Singleton
{
public:
    static Singleton* getInstance();
private:
    Singleton(){}                                    //构造函数私有
    Singleton(const Singleton&) = delete;            //明确拒绝
    Singleton& operator=(const Singleton&) = delete; //明确拒绝
​
    static Singleton* m_pSingleton;
};
​
Singleton* Singleton::m_pSingleton = new Singleton();
​
Singleton* Singleton::getInstance()
{
    return m_pSingleton;
}

最佳方案:

使用静态局部变量

class Single
{

public:
    // 获取单实例对象
    static Single &GetInstance();
    
    // 打印实例地址
    void Print();

private:
    // 禁止外部构造
    Single();

    // 禁止外部析构
    ~Single();

    // 禁止外部复制构造
    Single(const Single &signal);

    // 禁止外部赋值操作
    const Single &operator=(const Single &signal);
};

Single &Single::GetInstance()
{
    // 局部静态特性的方式实现单实例
    static Single signal;
    return signal;
}
上一篇下一篇

猜你喜欢

热点阅读