• 剑指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;
    }
  • 相关阅读:
    使用C#开发ActiveX控件 并制作Cab包
    asp.net后台创建table设置宽度百分比
    Sql按姓名查出某个人的成绩排名
    获得DataGridView多选框值
    解决iframe窗体丢失Session时登录窗口显示在子页面的问题
    xml返回数组数据
    安卓界面组件文本框
    安卓的UI界面开发(初学者推荐)
    安卓布局
    安卓界面组件按钮
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/8807171.html
Copyright © 2020-2023  润新知