设计模式之单例模式

来源:互联网 发布:网络大电影盈利模式 编辑:程序博客网 时间:2024/05/01 09:04

上篇我们讲了工厂模式,这章我们来聊聊单例模式,单例模式也是最常用的模式之一

在这篇里我要讲到懒汉式单例(经典单例)和饿汉式单例,以及经典单例的修改等。


经典单例:

以下代码在VS2012上编译通过

.h文件class singleton{private: singleton(); static singleton* mInstance;public: static singleton* getInstance();};.cpp文件singleton::singleton(){}singleton* singleton::getInstance(){ if(mInstance==NULL) {  mInstance=new singleton(); } return mInstance;}singleton* singleton::mInstance=NULL;


调用文件:

int _tmain(int argc, _TCHAR* argv[]){singleton* instance= singleton::getInstance();singleton* instance2= singleton::getInstance();if(instance==instance2){cout<<"The same"<<endl;}return 0;}
执行结果:

The same

       在上面我们可以看到经典单例模式的构造过程:首先要该类不被其他外部调用实例化,就要将构造函数设为私有权限,然后又通过公共的静态方法来实例化这个类,返回实例化后的对象的指针,然后通过内部私有指针mInstance来保存这个返回的指针,这样我们就可以使用这个类了。但是怎么来保证这个实例的唯一性呢?我们在静态方法getInstance()中要先判断,如果mInstance是为NULL的(mInstance要初始化为NULL),那么我们才实例化这个类。


问题:以上的单例模式如果在多线程中会怎么样呢?

    我们可以想想这种情况,如果线程1在进入了if(mInstance==NULL) 这个判断区域内的时候,要去实例化类,这个过程中要对新的实例各种初始化完之后才将新的实例的内存地址赋值给mInstance,也就是说这段时间内,mInstance也是等于NULL的,如果这个时候线程2再来实例化一次,还是能进入if(mInstance==NULL) 这个判断区域内的。所以最终我们就得到了两个不一样的实例,这显然是有悖于单例模式初衷的。


解答:方法一,任何一个线程可以在进入if(mInstance==NULL)之前加锁,然后出来后解锁。 方法二,饿汉单例模式


饿汉单例模式:

为什么称为饿汉单例模式呢?本质上就是刚创建这个类的时候就实例化这个类了,而不是要用到的时候再去实例化,既然使用过程中没有创建新的实例,自然就不可能有两个实例了。


h文件
class singleton{private: singleton(); static singleton* mInstance;public: static singleton* getInstance();};.cpp文件singleton::singleton(){}singleton* singleton::getInstance(){ return mInstance;}singleton* singleton::mInstance=new singleton();

       由以上可以看出饿汉单例模式,每次getInstance()的调用过程中,完全没有实例化的操作,从根本上杜绝了两个实例的现象。虽然一开始就要占一点内存,不过在多线程中利比弊大多了,好了今天就写到这里了,肚子饿了。。。饿汉+1偷笑


1 0
原创粉丝点击