【设计模式】单例模式

来源:互联网 发布:知乎周刊哪里下 编辑:程序博客网 时间:2024/06/18 08:42

单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

有很多地方需要这样的功能模块,如系统的日志输出,GUI应用必须是单鼠标,MODEM的联接需要一条且只需要一条电话线,操作系统只能有一个窗口管理器,一台PC连一个键盘。

《设计模式》一书中给出了一种很不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态方法获取该实例。

单例模式通过类本身来管理其唯一实例,这种特性提供了解决问题的方法。唯一的实例是类的一个普通对象,但设计这个类时,让它只能创建一个实例并提供对此实例的全局访问。唯一实例类Singleton在静态成员函数中隐藏创建实例的操作。习惯上把这个成员函数叫做GetInstance(),它的返回值是唯一实例的指针。

用户访问唯一实例的方法只有GetInstance()成员函数。如果不通过这个函数,任何创建实例的尝试都将失败,因为类的构造函数是私有的。

单例类CSingleton有以下特征:
它有一个指向唯一实例的静态指针m_pInstance,并且是私有的;
它有一个公有的函数,可以获取这个唯一的实例,并且在需要的时候创建该实例;
它的构造函数是私有的,这样就不能从别处创建该类的实例。

不考虑线程安全的单例类

class Singleton{public:    static Singleton* GetInstent()  //定义的静态成员函数获取对象实例    {        if(_sInstance == NULL)        {            _sInstance == new Singleton();        }        return _sInstance;    }private:    Singleton() //构造函数定义为私有,限制只能在类内创建对象    :_data(0)    {}    Singleton(const Singleton&);    Singleton& operator=(const Singleton&);    static Singleton* _sInstance; //指向实例的指针,定义为私有    int _data; //单例类里面的数据}

线程安全的单例类
懒汉模式:lazy loading 第一次调用GetInstance才创建实例对象,复杂
饿汉模式:程序一运行就创建实例对象,简洁高效,有些场景下不适用

a. 饿汉:

局部静态变量 类内没有定义指向实例的指针

static Singleton1* GetInstance(){    static Singleton1 instance;    return &instance;}

静态指针

static Singleton2* GetInstance(){    assert(_sInstance);    return _sInstance;}类外:Singleton2* Singleton2::_sInstance = new Singleton2;

b. 懒汉
1. 多个线程调用只用加两次锁,减少性能开销

static Singleton3* GetInstance(){    if(_sInstance == NULL) // 提高效率    {        lock();        if(_sInstance ==NULL) //保证线程安全        _sInstance = new Singleton();        unlock();    }    return _sInstance;}类外:Singleton3* singleton3::_sInstance = NULL;

2.RAII:加锁,出了作用域析构,避免线程加锁后出异常而没有解锁

static Singleton4* GetInstnce(){    if(_sInstance == NULL)    {        lock_guard<mutex> lg(_mtx);        if(_sInstance == NULL)        {            Singleton* tmp = new Singleton3;            MemoryBarrier(); //内存栅栏,防止优化            _sInstance = tmp;        }    }    return _sInstance;}成员变量:static metux _mtx;类外:Singleton4* Singleton4::_sInstance = NULL;     mutex Singleton4::_mtx; 
0 0
原创粉丝点击