zoukankan      html  css  js  c++  java
  • 设计模式之单例模式

     单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
        主要解决:一个全局使用的类频繁地创建与销毁。
        何时使用:想控制实例数目,节省系统资源的时候。
        如何解决:判断系统是否已存在单例,如果有则返回,没有则创建。
        关键代码:构造函数是私有的。

     单例大约有两种实现方法:懒汉与饿汉。
        懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化,所以上边的经典方法被归为懒汉实现;
        饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。
     特点与选择:
        由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
        在访问量较小时,采用懒汉实现。这是以时间换空间。

    //懒汉式一般实现:非线程安全,getInstance返回的实例指针需要delete
    class Singleton
    {
    public:
        static Singleton* getInstance();
        ~Singleton(){}
    
    private:
        static Singleton* m_pSingleton;
        Singleton(){}    
        Singleton(const Singleton& obj) = delete;  //明确拒绝
        Singleton& operator=(const Singleton& obj) = delete; //明确拒绝
    };
    
    Singleton* Singleton::m_pSingleton = NULL;
    
    Singleton* Singleton::getInstance()
    {
        if(m_pSingleton == NULL)
        {
            m_pSingleton = new Singleton;
        }
        return m_pSingleton;
    }
    //END
    
    //懒汉式:加lock,线程安全
    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();
            m_pSingleton = new Singleton();
            mt.unlock();
        }
        return m_pSingleton;
    }
    //END
    
    //返回一个reference指向local static对象
    //多线程可能存在不确定性:任何一种non-const static对象,不论它是local或non-local,在多线程环境下“等待某事发生”都会有麻烦。解决的方法:在程序的单线程启动阶段手工调用所有reference-returning函数。
    class Singleton
    {
    public:
        static Singleton& getInstance();
    private:
        Singleton(){}
        Singleton(const Singleton&) = delete;  //明确拒绝
        Singleton& operator=(const Singleton&) = delete; //明确拒绝
    };
    
    
    Singleton& Singleton::getInstance()
    {
        static Singleton singleton;
        return singleton;
    }
    //END
    
    //饿汉式:线程安全,注意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;
    }
    //END
  • 相关阅读:
    单进程架构数据库谨防隐形杀手
    21.2 超时与重传的简单例子
    19日下午三点直播:DevOps体系中数据库端的四大问题及解决之道
    SQL无所不能:DBA宝妈宝爸系列分享
    用Excel做了7天报表,这个领导喜欢的可视化工具,只用了7小时
    从块结构谈表的存储参数与性能之间的关系
    MYSQL SHELL 到底是个什么局 剑指 “大芒果”
    大数据构架师经典学习宝典
    POJ 3171 区间最小花费覆盖 (DP+线段树
    POJ 3171 区间最小花费覆盖 (DP+线段树
  • 原文地址:https://www.cnblogs.com/boost/p/10538717.html
Copyright © 2011-2022 走看看