您的位置:首页 > 其它

单件模式(singleton pattern)

2015-09-02 10:00 483 查看
看到有的书上的单件模式是这样的:
singleton.h:

class Singleton {
public :
static Singleton *GetInstance();
private :
Singleton();
static Singleton *s_singleton;
};


singleton.cpp :

Sington::Singleton() {

}

Singleton *Singleton::s_singleton = nullptr;

Singleton *Singleton::GetInstance() {
if (nullptr == s_singleton) {
s_singleton = new Singleton;
}

return s_singleton;
}


这样在single.cpp里面的定义的static成员变量是属于non-local成员变量(除了在函数体内定义的static对象称为local static 对象,其他的static对象都称为non-local static 对象,包括全局对象,静态全局变量,定义于namespace 中的对象,类静态成员)。但是这样的定义方法是不好的,因为当类逐渐多起来,类之间的以来关关系越来越复杂的时候,我们就可能会遇到初始化次序问题。为了避免这个问题,我们就应该把non-local
static对象转换成为local static对象。
举个例子(为了简单起见,违反了很对规范,莫怪~):
a.h:
<pre name="code" class="html">class A{
public :
int _i;
};

extern A a;    //  允许其他文件使用这个变量




b.h :
#include "a.h"

class B{
public :
B(A a){ printf("%d", a._i);}
};


这样的话,B可能会用用到尚未初始化的A类型的外部变量,也就是non-local static变量。而C++对编译于不同的编译单元内的non-local static对象的初始化次序也没有明确定义。

要解决这个问题就压迫把non-local static对象编程local static对象。
我们都知道,C++语法中有这样的说明,函数内的静态变量在函数调用期间第一次遇上静态变量的定义的时候才会被初始化。所以,我们可以通过返回一个静态变量的引用来替换直接访问non-local对象(静态变量的生存期是从定义的地方开始,一直到程序结束,所以,不用担心会访问的静态对象被销毁)。
修改第一个例子:
sington.h
class Singleton {
public :
static Singleton &GetInstance();  //  返回值为引用类型
private:
Singleton();
//  没有了静态成员变量
};


singleton.cpp
Sington::Singleton() {

}

Singleton &Singleton::GetInstance() {
static Singleton s_singleton;
return s_singleton;
}


这样就可以避免以上提到的问题啦。通过GetInstance()函数,我们就能获得唯一的一个Singleton的实例啦。

更进一步的,如果想要生成不止一个,但是又不是无限个对象的话,也可以通过单件模式实现。只要在生成对象的接口函数中加上一个静态变量和一个判断就可以了。

例如,我们现在有一个名为Boy的类。我们想只能生成10个Boy,避免男孩太多(生太多会被罚款的,虽然10个也会)。如果你觉得太多,也可以改成两个。
我们提供一个接口函数--getBoy,这个函数返回一个指向Boy的指针,其实更好的做法是用一个智能指针作为返回值,不过在这里不是重点。
boy.h
#ifndef _BOY_H
#define _BOY_H

class Boy {
public :
Boy *getBoy();
private :
enum {MAXOFBOYCOUNT = 10};
Boy();
~Boy();
};

#endif // _BOU_H


boy.cpp
#include "boy.h"

Boy::Boy() {

}

Boy::~Boy() {

}

Boy *Boy::getBoy() {
static size_t count = 0;
if (count <= MAXOFBOYCOUNT) {
++count;
return new Boy();
}

return nullptr;
}


如果我们想改变要生成的男孩的个数,只要改变类中的匿名枚举类的值就好啦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: