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

单例模式:一个类始终只有一个对象,无法直接new对象,只能通过类的特定接口来创建对象,因此也属于创建类模式。

 

/*
首先,需要保证一个类只有一个实例;在类中,要构造一个实例,就必须调用类的构造函数,
如此,为了防止在外部调用类的构造函数而构造实例,需要将构造函数的访问权限标记为protected或private;
最后,需要提供要给全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。
*/
#include<iostream>
using namespace std;

class singleclass{
public:
    static singleclass* CreateInstance(){   //this function is to create object, so it has to be static
        if(sclassptr==NULL)  //check if it is first create
            sclassptr = new singleclass();
        return sclassptr;

    }
private:
    static singleclass* sclassptr;  //the unique object
    singleclass(){
    }
};
singleclass* singleclass::sclassptr=NULL; //static member need be initialized
int main(){
    singleclass* sclass1=singleclass::CreateInstance();
    singleclass* sclass2=singleclass::CreateInstance();
    if(sclass2==sclass1)
        cout<<"same class"<<endl;
    else cout<<"error singleclass"<<endl;
    return 0;
}

 

恩,我们需要考虑线程安全性,对不对?

因此我们再给static成员变量赋值的时候,需要锁。C++里没有锁,我们可以借用第三方库,例如boost。

一、懒汉模式:即第一次调用该类实例的时候才产生一个新的该类实例,并在以后仅返回此实例。

需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety.

使用double-check来保证thread safety.但是如果处理大量数据时,该锁才成为严重的性能瓶颈。

1、静态成员实例的懒汉模式:

复制代码
 1 class Singleton
 2 {
 3 private:
 4     static Singleton* m_instance;
 5     Singleton(){}
 6 public:
 7     static Singleton* getInstance();
 8 };
 9 
10 Singleton* Singleton::getInstance()
11 {
12     if(NULL == m_instance)
13     {
14         Lock();//借用其它类来实现,如boost
15         if(NULL == m_instance)
16         {
17             m_instance = new Singleton;
18         }
19         UnLock();
20     }
21     return m_instance;
22 }
复制代码

2、内部静态实例的懒汉模式

这里需要注意的是,C++0X以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 0X以前,仍需要加锁。

复制代码
 1 class SingletonInside
 2 {
 3 private:
 4     SingletonInside(){}
 5 public:
 6     static SingletonInside* getInstance()
 7     {
 8         Lock(); // not needed after C++0x
 9         static SingletonInside instance;
10         UnLock(); // not needed after C++0x
11         return instance; 
12     }
13 };
复制代码

二、饿汉模式:即无论是否调用该类的实例,在程序开始时就会产生一个该类的实例,并在以后仅返回此实例。

由静态初始化实例保证其线程安全性,WHY?因为静态实例初始化在程序开始时进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。

故在性能需求较高时,应使用这种模式,避免频繁的锁争夺。

复制代码
 1 class SingletonStatic
 2 {
 3 private:
 4     static const SingletonStatic* m_instance;
 5     SingletonStatic(){}
 6 public:
 7     static const SingletonStatic* getInstance()
 8     {
 9         return m_instance;
10     }
11 };
12 
13 //外部初始化 before invoke main
14 const SingletonStatic* SingletonStatic::m_instance = new SingletonStatic;
复制代码
posted @ 2016-08-09 21:20  0giant  阅读(456)  评论(0编辑  收藏  举报