單例模式:保證一個(gè)類僅有一個(gè)實(shí)例怯晕,并提供一個(gè)訪問它的全局訪問點(diǎn)被碗。
單例模式分為懶漢式和餓漢式
懶漢式是當(dāng)該實(shí)例第一次被引用時(shí)窄锅,才將自己實(shí)例化明吩;
餓漢式是在被加載時(shí)就將自己實(shí)例化了蔑舞。
懶漢式
class Singleton{
public:
static Singleton* getInstance();
void doSomething();
void destroy();
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Singleton* instance;
};
Singleton* Singleton::instance = NULL;
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
if(instance == NULL)
instance = new Singleton();
return instance;
}
void Singleton::destroy() {
delete this;
instance = NULL;
}
int main() {
Singleton::getInstance()->doSomething();
Singleton::getInstance()->destroy();
return 0;
}
懶漢式是線程不安全的拒担,當(dāng)單例模式應(yīng)用在多線程中,應(yīng)該使用鎖進(jìn)行同步
class Singleton{
public:
static Singleton* getInstance();
void doSomething();
void destroy();
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Singleton* instance;
};
Singleton* Singleton::instance = NULL;
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
if(instance == NULL) {
lock();
if(instance == NULL)
instance = new Singleton();
unlock();
return instance;
}
void Singleton::destroy() {
delete this;
instance = NULL;
}
int main() {
Singleton::getInstance()->doSomething();
Singleton::getInstance()->destroy();
return 0;
}
而餓漢式是線程安全的
class Singleton{
public:
static Singleton* getInstance();
void doSomething();
void destroy();
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Singleton* instance;
};
Singleton* Singleton::instance = new Singleton();
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
return instance;
}
void Singleton::destroy() {
delete this;
instance = NULL;
}
int main() {
Singleton::getInstance()->doSomething();
Singleton::getInstance()->destroy();
return 0;
}
優(yōu)缺點(diǎn)
餓漢式
優(yōu)點(diǎn)
1. 線程安全
2. 在類加載的同時(shí)已經(jīng)創(chuàng)建好一個(gè)靜態(tài)對象斗幼,調(diào)用時(shí)反應(yīng)速度快
缺點(diǎn)
資源效率不高澎蛛,可能getInstance()永遠(yuǎn)不會執(zhí)行到,但執(zhí)行該類的其他靜態(tài)方法蜕窿,那么這個(gè)實(shí)例仍然初始化
懶漢式
優(yōu)點(diǎn):
避免了餓漢式的那種在沒有用到的情況下創(chuàng)建事例谋逻,資源利用率高,不執(zhí)行g(shù)etInstance()就不會被實(shí)例桐经,可以執(zhí)行該類的其他靜態(tài)方法毁兆。
缺點(diǎn):
不是線程安全,在多線程中需要線程同步阴挣,同步加鎖的過程提高了系統(tǒng)的開銷
應(yīng)用場景
- 網(wǎng)站的計(jì)數(shù)器气堕,一般也是采用單例模式實(shí)現(xiàn),否則難以同步畔咧。
- 應(yīng)用程序的日志應(yīng)用茎芭,一般都何用單例模式實(shí)現(xiàn),這一般是由于共享的日志文件一直處于打開狀態(tài)誓沸,因?yàn)橹荒苡幸粋€(gè)實(shí)例去操作梅桩,否則內(nèi)容不好追加。
- Web應(yīng)用的配置對象的讀取拜隧,一般也應(yīng)用單例模式宿百,這個(gè)是由于配置文件是共享的資源。
- 數(shù)據(jù)庫連接池的設(shè)計(jì)一般也是采用單例模式洪添,因?yàn)閿?shù)據(jù)庫連接是一種數(shù)據(jù)庫資源垦页。數(shù)據(jù)庫軟件系統(tǒng)中使用數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關(guān)閉數(shù)據(jù)庫連接所引起的效率損耗干奢,這種效率上的損耗還是非常昂貴的痊焊,因?yàn)楹斡脝卫J絹砭S護(hù),就可以大大降低這種損耗忿峻。
- 多線程的線程池的設(shè)計(jì)一般也是采用單例模式宋光,這是由于線程池要方便對池中的線程進(jìn)行控制。
- 操作系統(tǒng)的文件系統(tǒng)炭菌,也是大的單例模式實(shí)現(xiàn)的具體例子罪佳,一個(gè)操作系統(tǒng)只能有一個(gè)文件系統(tǒng)。