1 意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2 适用性
在下面的情况下可以使用Singleton模式
[color=red]a)当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时;
b)当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需要更改代码就能适用一个扩展的实例时;[/color]
3 优点
[color=red] a)对唯一实例的受控访问;
因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它;
b)缩小名空间
Singleton模式是对全局变量的一种改进,它避免了那些存储唯一实例的全局变量名空间
c)允许对操作和表示的精化;
Singleton类可以有子类,而且这个扩展类的实例来配置一个应用时很容易的。你可以用你所需要的类的实例在运行时刻配置应用。
d)允许可变数目的实例;
e)比类操作更灵活;[/color]
[img]http://t25-3.yunpan.360.cn/p/800-600.bcf593b6c742a90de0a298edc3894d661cdc74a3.f305c7.jpg?t=a344bfb34b846467f2df389c48ad5ce8&d=20130821[/img]
标准的单例模式,仅适用于单线程
改进的单例模式,适用于多线程
[url]http://www.jellythink.com/archives/82[/url]中有一个更好的示范,更简洁明了
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2 适用性
在下面的情况下可以使用Singleton模式
[color=red]a)当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时;
b)当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需要更改代码就能适用一个扩展的实例时;[/color]
3 优点
[color=red] a)对唯一实例的受控访问;
因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它;
b)缩小名空间
Singleton模式是对全局变量的一种改进,它避免了那些存储唯一实例的全局变量名空间
c)允许对操作和表示的精化;
Singleton类可以有子类,而且这个扩展类的实例来配置一个应用时很容易的。你可以用你所需要的类的实例在运行时刻配置应用。
d)允许可变数目的实例;
e)比类操作更灵活;[/color]
[img]http://t25-3.yunpan.360.cn/p/800-600.bcf593b6c742a90de0a298edc3894d661cdc74a3.f305c7.jpg?t=a344bfb34b846467f2df389c48ad5ce8&d=20130821[/img]
标准的单例模式,仅适用于单线程
//
class ChocolateBoiler
{
private:
ChocolateBoiler()
{
m_bEmpty = true;
m_bBoiled = false;
}
public:
static ChocolateBoiler* getInstance()
{
if (m_pUniqueInstance == NULL)
{
//标准的单例模式,多线程下面有可能创建多个实例
m_pUniqueInstance = new ChocolateBoiler();
}
return m_pUniqueInstance;
}
~ChocolateBoiler()
{
if (m_pUniqueInstance != NULL)
{
delete m_pUniqueInstance;
}
}
void fill()
{
if (isEmpty())
{
m_bEmpty = false;
m_bBoiled = false;
//在锅炉内填满巧克力和牛奶的混合物
}
if (m_bEmpty)
{
cout << "[ChocolateBoiler::fill] Empty\n";
}
else
{
cout << "[ChocolateBoiler::fill] Full\n";
}
if (m_bBoiled)
{
cout << "[ChocolateBoiler::fill] Boiled\n";
}
else
{
cout << "[ChocolateBoiler::fill] Not Boil\n";
}
}
void drain()
{
if (!isEmpty() && isBoiled())
{
//排出煮沸的巧克力和牛奶
m_bEmpty = true;
}
if (m_bEmpty)
{
cout << "[ChocolateBoiler::drain] Empty\n";
}
else
{
cout << "[ChocolateBoiler::drain] Full\n";
}
}
void boil()
{
if (!isEmpty() && !isBoiled())
{
//将炉内物煮沸
m_bBoiled = true;
}
if (m_bBoiled)
{
cout << "[ChocolateBoiler::boil] Boiled\n";
}
else
{
cout << "[ChocolateBoiler::boil] Not Boil\n";
}
}
bool isEmpty()
{
return m_bEmpty;
}
bool isBoiled()
{
return m_bBoiled;
}
private:
bool m_bEmpty;
bool m_bBoiled;
static ChocolateBoiler* m_pUniqueInstance;
};
ChocolateBoiler* ChocolateBoiler::m_pUniqueInstance = 0;
class ChocolateBoilerTestDrive
{
public:
void run()
{
ChocolateBoiler* pInstance = ChocolateBoiler::getInstance();
pInstance->fill();
pInstance->boil();
pInstance->drain();
ChocolateBoiler* pInstance2 = ChocolateBoiler::getInstance();
//pInstance->fill();
pInstance2->boil();
pInstance2->drain();
}
};
改进的单例模式,适用于多线程
class Singleton
{
public:
static Singleton* getInstance()
{
if (m_pUniqueInstance == NULL)
{
//解决多线程问题
//方法一
//进入同步状态,采用双重检查,这是jave的做法
static Singleton singleton = Singleton();
m_pUniqueInstance = &singleton;
//方法二
//创建临界区
//EnterCriticalSection(&g_cs);
//if (m_pUniqueInstance == NULL) //双重检查
//{
// m_pUniqueInstance = new Singleton();
//}
//LeaveCriticalSection(&g_cs);
}
return m_pUniqueInstance;
}
private:
Singleton(){}
~Singleton()
{
if (m_pUniqueInstance != NULL)
{
delete m_pUniqueInstance;
}
}
private:
static Singleton* m_pUniqueInstance;
};
Singleton* Singleton::m_pUniqueInstance = 0;
[url]http://www.jellythink.com/archives/82[/url]中有一个更好的示范,更简洁明了
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton *GetInstance()
{
static Singleton m_Instance;
return &m_Instance;
}
int GetTest()
{
return m_Test++;
}
private:
Singleton(){ m_Test = 10; };
int m_Test;
};
int main(int argc , char *argv [])
{
Singleton *singletonObj = Singleton ::GetInstance();
cout<<singletonObj->GetTest()<<endl;
singletonObj = Singleton ::GetInstance();
cout<<singletonObj->GetTest()<<endl;
}