c++设计模式之单例模式

  1. 单例模式概念
    单例模式事比较常用的设计模式之一。一般情况下,我们建立的一些类是属于工具性质的,基本不用存储太多的跟自身有关的数据,在这种情况下,每次都去new一个对象,即增加了开销,也使得代码更加臃肿。其实,我们只需要一个实例对象就可以。如果采用全局或者静态变量的方式,会影响封装性,难以保证别的代码不会对全局变量造成影响,而且这样的代码显的很不优雅。 使用全局对象能够保证方便地访问实例,但是不能保证只声明一个对象——也就是说除了一个全局实例外,仍然能创建相同类的本地实例。
    我们将默认的构造函数声明为私有的,这样就不会被外部所new了,甚至可以将析构函数也声明为私有的,这样就只有自己能够删除自己了。
  2. 单例模式的懒汉模式和饿汉模式
    懒汉模式:就是不到万不得已是不会去实例化类的,也就是说在第一次用到类实例的时候才会去实例化。
    饿汉模式:在单例类定义的时候就实例化了。
    优点和缺点:
    (1)在访问量比较小的时候,采用懒汉模式。以时间换空间。
    (2)因为要进行线程同步,所以在访问量较多的时候,采用饿汉模式,可以实现更好的性能。以空间换时间。
    实现:把构造函数定义为私有的或者保护的,再定义一个类的私有的静态指针,指向这个类的唯一实例,再提供一个公有的静态的方法获取该实例。
  3. 代码实现
    《一》饿汉模式
    (1)饿汉模式实现一
class SiglenTon      //懒汉模式(线程不安全)
{
public:
    static SiglenTon *GetInstance()
    {
        if( ptr == NULL)
        {
            ptr = new SiglenTon();
        }
        return ptr;
    }
private:
    SiglenTon()
    {
        cout<<"SiglenTon()"<<endl;
    }
    static SiglenTon *ptr;
};
SiglenTon *SiglenTon::ptr = NULL;
int main()
{
    SiglenTon *ptr = SiglenTon::GetInstance();
    return 0;
}

该方式实现的单例模式是不安全的,假如有两个线程同时调用GetInstance的时候,同时检测到ptr指针为空,同时创建一个相同的对象,这是错误的。
(2)饿汉模式实现二(加一层互斥锁)

class SigleTon     
{
public:
    static SigleTon *GetInstance()
    {
        cout<<"static SigleTon *GetInstance()"<<endl;
        pthread_mutex_lock(&mutex);   
        if( ptr == NULL)
        {
            ptr = new SigleTon(); 
        }
        pthread_mutex_unlock(&mutex);
        return ptr;
    }
private:
    SigleTon()
    {
        cout<<"SigleTon()"<<endl;
    }
    static SigleTon *ptr;
};
SigleTon *SigleTon::ptr = NULL;

该方式加了一对互斥锁,线程是安全的,但是对于单线程来说,每次都要加锁解锁,效率不高。而且如果每次判断是否为空都需要被锁定,如果有很多线程的话,就会造成大量线程的阻塞。
(3)饿汉模式实现三(两层互斥锁)

class SigleTon   //加双重互斥锁
{
public:
    static SigleTon *GetInstance()
    {
        cout<<"static SigleTon *GetInstance()"<<endl;
        pthread_mutex_lock(&mutex);  
        if( ptr == NULL)
        {
            pthread_mutex_lock(&mutex);
            ptr = new SigleTon(); 
            pthread_mutex_lock(&mutex);
        }
        pthread_mutex_unlock(&mutex);
        return ptr;
    }
private:
    SigleTon()
    {
        cout<<"SigleTon()"<<endl;
    }
    static SigleTon *ptr;
};
SigleTon *SigleTon::ptr = NULL;

(4)饿汉模式实现四(用一个静态内部变量实现懒汉模式)
在Instance函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针就可以了。推荐这种实现方法,真得非常简单。

class SiglenTon   
{
public:
    static SiglenTon *Instance()
    {
        cout<<"static SiglenTon Instance()"<<endl;
        pthread_mutex_lock(&mutex);
        static SiglenTon msigleton;
        pthread_mutex_lock(&mutex);
        return &msigleton;
    }
private:
    SiglenTon()
    {
        cout<<"SiglenTon()"<<endl;
    }
    static SiglenTon *ptr;
};
SiglenTon *SiglenTon::ptr = NULL;

《二》懒汉模式
在类外初始化指针的时候就创建一个对象。懒汉模式是线程安全的,不用加互斥锁,因为在当类定义的时候定义了一个对象,对类进行了初始化。后面不管哪个线程调用Instance函数,都只不过是返回了一个对象的指针而已。

class SigleTon
{
public:
    static SigleTon *GetInstance()
    {
        cout<<"static SigleTon *GetInstance()"<<endl;
        if( ptr == NULL)
        {
            return ptr;
        }
    }
private:
    SigleTon()
    {
        cout<<"SigleTon()"<<endl;
    }
    static SigleTon *ptr;
};
SigleTon *SigleTon::ptr  = new SigleTon();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值