单例模式

  • 单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了一种访问其唯一的对象的方法,可以直接访问,不需要实例化该类的对象。
  • 注意:
    1、单例类只能有一个实例;
    2、单例类必须自己创建自己的唯一的实例;
    3、单例类必须给所有其他对象提供这一实例;

主要解决的问题:一个全局使用的类频繁地创建和销毁;
使用时机:当你想控制实例数目,节省系统资源的时候;
解决办法:判断系统是否已经有这个实例,如果有则返回,如果没有则创建;
关键代码:构造函数是私有的;

  • 优点:
    1、在内存中 只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁的实例;
    2、避免对资源的多重占用(比如写文件操作);
  • 缺点
    没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化;
  • 使用场景:
    1、要求生产唯一的序列号;
    2、创建一个对象需要消耗的资源过多,比如I/O与数据库的连接等
  • 注意:
    getInstance()方法中需要使用同步锁syschronized()防止多线程同时进入instance被多次实例化;
  • 懒汉模式
    顾名思义,不到万不得已就不去实例化,也就是第一次用到类实例的时候才会去实例化;
    在访问量较小时,采用懒汉实现,这是以时间换空间
#include <iostream>
using namespace std;
class Singleton
{
    public:
        static Singleton* GetInstance();
    private:
        Singleton()
        {
            cout<<"创建单例对象"<<endl;
        };
        Singleton(const Singleton&){};//禁止拷贝
        Singleton& operator = (const Singleton&){};//禁止赋值
        
        static Singleton* instance;
};
//初始化
Singleton* Singleton::instance = NULL;
Singleton* Singleton::GetInstance(){
    if(instance == NULL){
        instance = new Singleton();
    }
    return instance;
}
int main()
{
    Singleton::GetInstance();
    Singleton::GetInstance();
}
/////////////////////////输出结果//////////////////
创建单例对象

以上代码示例中虽然调用了两次Singleton::GetInstance()函数,但只调用了一次构造函数实例化对象;
注意:懒汉模式下,在定义intance变量时先等于NULL,在调用GetInstance()方法时,再判断是否要赋值。这种模式下,并非是线程安全的,因为多个线程在调用GetInstance()方法,就可能导致有产生多个实例。要实现线程安全就必须加锁。

//加锁的懒汉模式
#include <iostream>
using namespace std;

class Singleton
{
private:
    Singleton(){
        pthread_mutex_init(&mutex); 
    };
    Singleton(const Singleton&){};
    Singleton& operator=(const Singleton&){};
    static Singleton* instance;
public:
    static pthread_mutex_t mutex;
    static Singleton* GetInstance();
};

pthread_mutex_t Singleton::mutex;
Singleton* Singleton::instance = NULL;

Singleton* Singleton::GetInstance(){
    if(instance == NULL){
        pthread_mutex_lock(&mutex);
        if(instance == NULL)
            instance = new Singleton();
        pthread_mutex_unlock(&mutex);
    }
    return instance;
}

  • 饿汉模式
    优点:线程安全,还未使用变量时,已经对instance进行赋值,就像很饥饿的感觉。在多线程环境下肯定是线程安全的,因为不存在多线程实例化的问题。
    饿了肯定饥不择食,所以在单例类定义的时候就进行实例化;
    由于要进行线程同步,所以访问量比较大,或者可能访问的线程比较多,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
#include <iostream>
using namespace std;
class Singleton
{
    public:
        static Singleton* GetInstance();
    private:
        Singleton()
        {
            cout<<"创建单例对象"<<endl;
        };
        Singleton(const Singleton&){};//禁止拷贝
        Singleton& operator = (const Singleton&){};//禁止赋值
        
        static Singleton* instance;
};
//初始化
Singleton* Singleton::instance = new Singleton();
Singleton* Singleton::GetInstance()
{
    return instance;
}
int main()
{

}
/////////////////运行结果/////////////////////
创建单例对象
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。