這個模式應該是設計模式中最簡單的一個了,可分爲懶漢式、餓漢式。
下面就分別貼上代碼:
/*****************************************
Copyright (c) 2016 Jingshuang Hu
@filename:main.cpp
@datetime:2016.09.13
@author:HJS
@e-mail:[email protected]
@blog:http://blog.csdn.net/hujingshuang
*****************************************/
#include <iostream>
using namespace std;
// 懶漢式:也就是說在需要創建實例的時候,才調用該函數來創建,不需要的時候就不創建,起到lazy loading的作用。
// 這種最基本的寫法線程不安全。如果加同步鎖,可以解決線程安全問題,但同時會導致效率低下。
class Singleton {
private:
static Singleton* singleton;
Singleton() {} // 私有
~Singleton() {}
Singleton(const Singleton&); // 聲明爲私有,只聲明不實現,明確拒絕編譯器默認的拷貝構造函數
Singleton& operator=(const Singleton); // 聲明爲私有,只聲明不實現,明確拒絕編譯器默認的賦值操作函數
public:
static Singleton* getInstance() {
if (singleton == NULL) {
singleton = new Singleton(); // 調用的時候才創建實例
}
return singleton;
}
};
Singleton* Singleton::singleton = NULL; // 類外初始化
int main() {
Singleton* singleton1 = Singleton::getInstance();
Singleton* singleton2 = Singleton::getInstance();
if (singleton1 == singleton2) { // 創建的是同一個實例
cout << "equal" << endl;
}
system("pause");
return 0;
}
// 這是一種餓漢式方法,程序一開始就初始化靜態變量(即:創建了Singleton對象)
class Singleton {
private:
static Singleton singleton;
Singleton() {
cout << "ctor" << endl;
}
~Singleton() {
cout << "dctor" << endl;
}
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static Singleton* getInstance() { // 返回指針
cout << "instance" << endl;
return &singleton;
}
void fun() {
cout << "fun" << endl;
}
};
Singleton Singleton::singleton;
// 這是一種不好的做法,因爲這裏的singleton被動態的初始化,無法保證編譯器一定先將singleton初始化
// 因此Singleton::singleton的調用,可能傳回一個尚未構造的函數,因此導致使用該類成員函數出錯!(書《Modern C++ Design》)
int main() {
Singleton::getInstance()->fun();
Singleton* singleton1 = Singleton::getInstance();
Singleton* singleton2 = Singleton::getInstance();
if (singleton1 == singleton2) { // 創建的是同一個實例
cout << "equal" << endl;
}
system("pause");
return 0;
}
// 引用版
class Singleton {
private:
static Singleton* singleton;
Singleton() {
cout << "ctor" << endl;
}
~Singleton() {
cout << "dctor" << endl;
}
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static Singleton& getInstance() { // 返回引用,相對指針要安全
cout << "instance" << endl;
return *singleton;
}
void fun() {
cout << "fun" << endl;
}
};
Singleton* Singleton::singleton;
// 這是一種不好得做法,因爲這裏的singleton被動態的初始化,無法保證編譯器一定先將singleton初始化
// 因此Singleton::singleton的調用,可能傳回一個尚未構造的函數,因此導致使用該類成員函數出錯!
int main() {
Singleton::getInstance().fun(); // 在不同的編譯器上可能會出錯
Singleton& singleton1 = Singleton::getInstance();
Singleton& singleton2 = Singleton::getInstance();
if (&singleton1 == &singleton2) {
cout << "equal" << endl;
}
system("pause");
return 0;
}
// 這是一種懶漢式做法,而且是線程安全的
class Singleton {
private:
Singleton() {}
~Singleton(){};
Singleton(const Singleton&);
Singleton& operator=(const Singleton);
public:
static Singleton& getIntance() {
static Singleton singleton; // 局部靜態類變量,其初始化發生在第一次定義時(也就是第一次調用此函數時)
return singleton;
}
void fun() {
cout << "fun" << endl;
}
};
int main() {
Singleton& singleton1 = Singleton::getIntance();
Singleton& singleton2 = Singleton::getIntance();
if (&singleton1 == &singleton2) {
cout << "equal" << endl;
}
system("pause");
return 0;
}
// 餓漢式:也就是說程序一開始就創建實例,不管用沒用到,保證了線程安全,但未起到lazy loading的效果。
class Singleton {
private:
static Singleton* singleton;
Singleton() {}
~Singleton() {}
Singleton(const Singleton&);
Singleton& operator=(const Singleton);
public:
static Singleton* getInstance() {
return singleton;
}
void fun() {
cout << "fun" << endl;
}
};
Singleton* Singleton::singleton = new Singleton(); // 不管需不需要,程序一上來就給創建實例
int main() {
Singleton* singleton1 = Singleton::getInstance();
Singleton* singleton2 = Singleton::getInstance();
if (singleton1 == singleton1) {
cout << "equal" << endl;
}
system("pause");
return 0;
}