设计模式 --> (2)单例模式

单例模式

  单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。如系统的日志输出,GUI应用必须是单鼠标,MODEM的联接需要一条且只需要一条电话线,操作系统只能有一个窗口管理器,一台PC连一个键盘。单例模式有两种:饿汉式单例类懒汉式单例类。

适用性:

  单例模式常常与工厂模式结合使用,因为工厂只需要创建产品实例就可以了,在多线程的环境下也不会造成任何的冲突,因此只需要一个工厂实例就可以了。

优点:

  1.减少了时间和空间的开销(new实例的开销)。

  2.提高了封装性,使得外部不易改动实例。

缺点:

  1.懒汉式是以时间换空间的方式。

  2.饿汉式是以空间换时间的方式。

饿汉式单例类

//外部初始化 before invoke main
const Singleton* Singleton::m_instance = new Singleton;

class Singleton
{
private:
    static const Singleton* m_instance;
    Singleton(){}
public:
    static const Singleton* getInstance()
    {
        return m_instance;
    }
};

懒汉式单例类

class Singleton
{
private:
    static Singleton* m_instance;
    Singleton() {}
public:
    static Singleton* getInstance();
};

Singleton* Singleton::getInstance()
{
    if(NULL == m_instance)
    {
        m_instance = new Singleton;
    }

    return m_instance;
}

但是在多线程的环境下却不行了,因为很可能两个线程同时运行到if (m_instance == NULL)这一句,导致可能会产生两个实例。于是就要在代码中加锁。

Singleton* getInstance()
{
    lock();
    if (instance == NULL)
    {
       instance= new Singleton();
    }
    unlock();

    return instance;
}

但这样写的话,会稍稍影响性能,因为每次判断是否为空都需要被锁定,如果有很多线程的话,就爱会造成大量线程的阻塞。于是大神们又想出了双重锁定。

Singleton* getInstance()
{
    if (instance == NULL)
    {
        lock();
        if (instance == NULL)
        {
               instance = new Singleton();
        }
        unlock();
    }

    return instance;
}

这样只够极低的几率下,通过越过了if (instance == NULL)的线程才会有进入锁定临界区的可能性,这种几率还是比较低的,不会阻塞太多的线程,但为了防止一个线程进入临界区创建实例,另外的线程也进去临 界区创建实例,又加上了一道防御if (instance == NULL),这样就确保不会重复创建了。

使用

#include <iostream>
using namespace std;

// 单例模式
class Singleton
{
private:
    Singleton() {}; // 不允许直接构造其对象
    static Singleton *instance;

public:
    static Singleton* createInstance()
    {
        if(!instance)
        {
            // 对象第一次被创建,允许
            cout << "创建新对象" << endl;
            instance = new Singleton();
        }
        else
        {
            // 请求再次创建对象,不允许
            cout << "已经创建过对象了,返回原对象" << endl;
        }

        return instance;
    }

    void getAddress()
    {
        cout << "我的地址是 " << instance << endl;
    }
};

Singleton* Singleton::instance = 0; //在初始化的时候,不能在前面加static了

int main()
{
    //Singleton s;//报错:无法访问 private 成员(在“Singleton”类中声明)
    Singleton *s1 = Singleton::createInstance();
    s1->getAddress();
    cout << endl << endl;
    
    Singleton *s2 = Singleton::createInstance();
    s2->getAddress();
    return 0;
}
原文地址:https://www.cnblogs.com/jeakeven/p/4911930.html