<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:新宋体; panose-1:2 1 6 9 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@新宋体"; panose-1:2 1 6 9 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:modern; mso-font-pitch:fixed; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} h1 {mso-style-priority:9; mso-style-unhide:no; mso-style-qformat:yes; mso-style-link:"标题 1 Char"; mso-style-next:正文; margin-top:17.0pt; margin-right:0cm; margin-bottom:16.5pt; margin-left:0cm; text-align:justify; text-justify:inter-ideograph; line-height:240%; mso-pagination:lines-together; page-break-after:avoid; mso-outline-level:1; font-size:22.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-font-kerning:22.0pt;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; text-indent:21.0pt; mso-char-indent-count:2.0; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} span.1Char {mso-style-name:"标题 1 Char"; mso-style-priority:9; mso-style-unhide:no; mso-style-locked:yes; mso-style-link:"标题 1"; mso-ansi-font-size:22.0pt; mso-bidi-font-size:22.0pt; mso-font-kerning:22.0pt; font-weight:bold;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:437336535; mso-list-type:hybrid; mso-list-template-ids:-1305449064 558520516 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l0:level1 {mso-level-tab-stop:none; mso-level-number-position:left; margin-left:39.0pt; text-indent:-18.0pt;} @list l1 {mso-list-id:678120701; mso-list-type:hybrid; mso-list-template-ids:1203147684 -156753692 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l1:level1 {mso-level-tab-stop:none; mso-level-number-position:left; margin-left:39.0pt; text-indent:-18.0pt;} @list l2 {mso-list-id:2057003552; mso-list-type:hybrid; mso-list-template-ids:-1968939722 -1554222414 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l2:level1 {mso-level-tab-stop:none; mso-level-number-position:left; margin-left:39.0pt; text-indent:-18.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} -->
Singleton 的标准实现
Singleton 模式是 GOF 23 个模式中最简单地,也是使用地比较广泛地一个模式。其结构如下图所示 :
其实现大家应该都很了解,不了解的就 Google 一下,要多少有多少,也可以参考附件中的 SingletonStd
生活有时不那么美好
Singleton 的 C++ 实现依赖于静态变量的使用,在可以使用静态变量的环境中,生活是美好的,可是这个世界上也存在不支持静态变量 (Brew,Symbian ,etc) 或者对静态变量的使用有诸多限制 (Brew Mobile Platform 不能在函数中使用静态变量 ) 的平台。在这种情况,你可能会嘟囔地骂编译器,并发誓说没有这个模式照样可以工作,但是我可以打赌,你不是认真地,你只不过是发发牢骚而已,最后要面对的依然是怎样让才能让 Singleton work 起来。
在实际工作中,我采用一种比较直接的方案,现记录下来以飨大家,同时欢迎大家多多拍砖,只是在拍的同时务请告知更好地解决办法。
搁哪儿啊
在你接受了现实,并开始思考解决方案的时候,第一个拦在你面前问题一定是: Singleton 该搁哪儿?天无绝人之路,对于不能使用静态变量的平台,一般来说都有一个代表那个 applet 的实例,它在程序启动时创建,在程序结束时销毁。而且会提供一个 help function ,让你可以在程序的任意地方获得这个实例。为了叙述方便,我把这个 Applet 取名为 AppInstance, 那个可以获取它 help function 叫 GetAppInstance() 。这样我们就可以把 Singleton 存在这个 AppInstance 中。可以在控制台中这样模拟 AppInstance 和 GetAppInstance:
#ifndef APPINSTANCE_HPP
#define APPINSTANCE_HPP
#include <vector>
#include <map>
#include <string>
using std::vector;
using std::string;
using std::map;
typedef void (*releaseFun)(void );
class AppInstance
{
public :
~AppInstance();
static AppInstance* GetInstance();
void RegisterSingleton(const string& strName,void * pSingleton);
void RegisterSingletonReleaseFun(releaseFun relFun);
void *& GetSingleton(const string& strName);
private :
map<string,void *> m_vSingleton; //store the instance of Singleton: (key,value) -- (name,pointer)
vector<releaseFun> m_vSingletonReleaseFun; //store the destructor of singleton
};
extern AppInstance* GetAppInstance();
#endif
这样你就可以将Singleton 存到AppInstance 之中,在附件Singleton 之中,你会发现AppInstance 的GetInstance 中使用了静态变量,这只是为了在控件台中模拟才这样的,在实际中你会有创建AppInstance 的时机的。
如果平台只支持类的静态变量,而不支持函数内的静态变量,我想大家都知道该存哪儿,我就不多唠叨了。
Singleton 的析构。
在平台支持静态变量的时候,我们可以像下面一样优雅地搞扼这个问题 :
Singleton* Singleton::GetInstance(void )
{
static Singleton g_oInstance;
return &g_oInstance;
}
对于不支持在函数内定义静态变量的平台,我也在百度上搜得一极具创意的实现,如下:
#ifndef _SINGLETONCHEAT_H
#define _SINGLETONCHEAT_H
#include <iostream>
using std::cout;
using std::endl;
class Singleton
{
public :
static Singleton* GetInstance()
{
if (0 == Singleton::g_pInstance)
{
Singleton::g_pInstance = new Singleton;
}
return Singleton::g_pInstance;
}
~Singleton()
{
cout<<__FUNCTION__<<endl;
}
private :
Singleton()
{
cout<<__FUNCTION__<<endl;
}
class SingletonCollector
{
public:
~SingletonCollector()
{
delete Singleton::g_pInstance;
}
};
static SingletonCollector collector;
static Singleton* g_pInstance;
};
Singleton* Singleton::g_pInstance = NULL;
Singleton::SingletonCollector Singleton::collector = Singleton::SingletonCollector();
#endif
如果平台干脆不支持静态变量,解决办法就不那么优雅了,你说可能会说在AppInstance 中一个个地删除就行了啊,我完全同意,可是我们要小心:
1. AppInstance 不知道每个Singleton ,直接delete 那个void* ,只相当于delete 了个int ,用户会抱怨内存用完了。
2. 如果你将Singleton 的头文件包含进来,那么就会引入那讨人厌的信赖,让你的维护成本一下子提高几倍。
有两种方案可以解决这个问题:
1. 让所有的 Singleton 从一个基类派 SingletonBase 生而来,将让这个基类的析构函数为虚,注册 Singleton 的时候传进的指针不再是 void* 而是 SingletonBase* 。
2. 为每个 Singleton 注册一个 release 函数到 AppInstance 中 , 我就是这么干的。
实现
解决掉上面的两个问题后, Singleton 的方便之门又为我们打开了。不过我是个懒人,不想每次写一个单例都要循规蹈矩地写一大堆代码,虽然我不喜欢宏,但是在这里它确实可以帮我,所以我就再破例使用一次 , 由于实现有差不多 100 行,大家自行参考 Singleton.zip 中的 SingletonDef.h ,其中,我定义了三个宏 :
1. DECLARE_SINGLETON(Singleton) : 用于在定义类时申明它是一个 Singleton ;
2. BEGIN_IMPLEMENT_SINGLETON(Singleton): 在实现类时开始实例化 Singleton 用 ;
3. END_IMPLEMENT_SINGLETON(Singleton) :结束 Singleton 的实例化。
现在,要写一个单例, 3 句话就搞定啦 , 看下面这个例子 ( 见附件中的 Singleton.zip):
//==================================file Singleton.h=============================================
#ifndef _SINGLETON_H
#define _SINGLETON_H
#include "SingletonDef.h"
class Singleton
{
DECLARE_SINGLETON(Singleton);
Singleton();
public :
~Singleton();
public :
void fun(void );
};
#endif
//==============================file Singleton.cpp==============================================================
#include "Singleton.h"
#include <iostream>
using std::cout;
using std::endl;
BEGIN_IMPLEMENT_SINGLETON(Singleton)
Singleton();
END_IMPLEMENT_SINGLETON(Singleton)
Singleton::Singleton()
{
cout<<__FUNCTION__<<endl;
}
Singleton::~Singleton()
{
cout<<__FUNCTION__<<endl;
}
void Singleton::fun(void )
{
cout<<__FUNCTION__<<endl;
}
最后要谢谢一下chengxiong兄,给我指出了一个白痴地错误