剑指Offer面试题:1.实现单例模式

一 题目:实现单例模式Singleton

题目:设计一个类,我们只能生产该类的一个实例。

  只能生成一个实例的类是实现了Singleton(单例)模式的类型。由于设计模式在面向对象程序设计中起着举足轻重的作用,在面试过程中很多公司都喜欢问一些与设计模式相关的问题。在常用的模式中,Singleton是唯一一个能够用短短几十行代码完整实现的模式。因此,写一个Singleton的类型是一个很常见的面试题。

二:单例模式的几种实现方法

(1)单线程单例模式

// 单例模式
class Singleton
{
private:
    Singleton(){}
    ~Singleton(){delete m_pSingleton;};

public:
    static Singleton* Instance();

private:
    static Singleton*m_pSingleton;
};

Singleton* Singleton::m_pSingleton = NULL;
Singleton* Singleton::Instance()
{
    if (!m_pSingleton)
    {
        m_pSingleton = new Singleton();
    }

    return m_pSingleton;
}

  这是一个很棒的实现,简单易懂。但这是一个完美的实现吗?不!该方法是线程不安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的唯一实现!

(2)懒汉单例模式

  a. 使用互斥对象实现懒汉模式

// 单例模式
class Singleton
{
private:
    Singleton(){};
    ~Singleton(){
        delete m_pSingleton;
        DeleteCriticalSection(&cs);}

public:
    static Singleton * Instance();

private:
    static Singleton *m_pSingleton;
    static CRITICAL_SECTION cs;
    static bool bInitCriticalSection;
};

CRITICAL_SECTION Singleton::cs = {0};
bool Singleton::bInitCriticalSection = false;
Singleton * Singleton::m_pSingleton = NULL;

Singleton * Singleton::Instance()
{
    if (!bInitCriticalSection)
    {
        InitializeCriticalSection(&cs);
        bInitCriticalSection = true;
    }
    if (!m_pSingleton)
    {
        EnterCriticalSection(&cs);
        m_pSingleton = new Singleton();
        LeaveCriticalSection(&cs);
    }

    return m_pSingleton;
}

  b. 使用内部静态变量实现懒汉模式

   此方法也很容易实现,在instance函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针就可以了。推荐这种实现方法,真得非常简单

// 单例模式
class Singleton
{
private:
    Singleton(){}
    ~Singleton(){DeleteCriticalSection(&cs);}

public:
    static Singleton * Instance();

private:
    static CRITICAL_SECTION cs;
    static bool bInitCriticalSection;
};

CRITICAL_SECTION Singleton::cs = {0};
bool Singleton::bInitCriticalSection = false;
Singleton * Singleton::Instance()
{
    if (!bInitCriticalSection)
    {
        InitializeCriticalSection(&cs);
        bInitCriticalSection = false;
    }
    EnterCriticalSection(&cs);
    static Singleton m_Singleton;
    LeaveCriticalSection(&cs);

    return &m_Singleton;
}

(3)饿汉单例模式

  饿汉实现本来就是线程安全的,不用加锁。为啥?自己想!

// 单例模式
class Singleton
{
private:
    Singleton(){};
    ~Singleton(){}

public:
    static Singleton * Instance();

private:
    static Singleton *m_pSingleton;
};

Singleton * Singleton::m_pSingleton = new Singleton();
Singleton * Singleton::Instance()
{
    return m_pSingleton;
}

 

posted @ 2018-04-12 14:17  Fate0729  阅读(994)  评论(0编辑  收藏  举报