簡述
單例,顧名思義,就是一個程序中,只能存在一個這樣的實例。所以要實現單例必須
- 私有化構造函數,禁止外部創建新的對象
- 私有化析構函數,防止資源不正確釋放
- 私有化拷貝構造函數,禁止拷貝出新的對象
- 私有化賦值運算符,禁止通過賦值創建出新的對象
- 提供獲取實例的方法
- 提供銷燬實例的方法
簡單實現
#include <iostream>
class Singleton
{
Singleton()
{
std::cout << "creator object" << std::endl;
}
~Singleton()
{
std::cout << "destroy object" << std::endl;
}
public:
static Singleton *Instance()
{
if(!self) {
self = new Singleton;
}
return self;
}
void destroy()
{
if(self) {
delete self;
self = NULL;
}
}
void dosomething()
{
std::cout << "do something" << std::endl;
}
private:
static Singleton *self;
Singleton(const Singleton &);
Singleton &operator = (const Singleton &);
};
Singleton *Singleton::self = NULL;
單例實現好了,來應用
int main(int , char *[])
{
Singleton *obj = Singleton::Instance();
obj->dosomething();
obj->destroy();
return 0;
}
輸出
creator object
do something
destroy object
無異常,但每次都需要在程序結束前手動刪除,可能會不小心漏了, 所以需要增加一個自動釋放資源的類。
在Singleton
中增加嵌套類GC
用於垃圾回收,由於嵌套類GC
使用了Singleton
中的私有靜態成員變量,所以GC
也必須私有化,防止在類外創建
class GC
{
public:
GC() { }
~GC()
{
if (self) {
delete self;
self = NULL;
}
}
};
修改獲取實例的方法
static Singleton *Instance()
{
if(!self) {
static GC gc;
self = new Singleton;
}
return self;
}
使用
int main(int , char *[])
{
Singleton*obj = Singleton::Instance();
obj->dosomething();
return 0;
}
輸出
creator object
do something
destroy object
這樣程序關閉時,就會自動釋放單例資源。
完整代碼
#include <iostream>
class Singleton
{
Singleton()
{
std::cout << "creator object" << std::endl;
}
~Singleton()
{
std::cout << "destroy object" << std::endl;
}
public:
static Singleton *Instance()
{
if(!self) {
static GC gc;
self = new Singleton;
}
return self;
}
void destroy()
{
if(self) {
delete self;
self = NULL;
}
}
void dosomething()
{
std::cout << "do something" << std::endl;
}
private:
static Singleton *self;
Singleton(const Singleton &);
Singleton &operator = (const Singleton &);
class GC
{
public:
GC() { }
~GC()
{
if (self) {
delete self;
self = NULL;
}
}
};
};
Singleton *Singleton::self = NULL;
int main(int , char *[])
{
Singleton *obj = Singleton::Instance();
obj->dosomething();
return 0;
}
單例工廠
有時候一個程序中存在大量單例,每個單例都需要重新實現這些方法,有沒有方法可以把這些重複的部分複用起來呢?
創建工廠
template <typename T>
class Factory
{
static T *singleton;
public:
static T *Instance()
{
if(!singleton) {
static GC gc;
singleton = new T;
}
return singleton;
}
private:
Factory() {} //禁止構造,禁止繼承
class GC
{
public:
GC() { }
~GC()
{
if (singleton) {
delete singleton;
singleton = NULL;
}
}
};
};
template <class T>
T *Factory<T>::singleton = NULL;
創建需要單例化的類
class Object
{
friend class Factory<Object>;
Object()
{
std::cout << "creator object" << std::endl;
}
~Object()
{
std::cout << "destroy object" << std::endl;
}
Object(const Object &);
Object &operator = (const Object &);
public:
void dosomething()
{
std::cout << "do something" << std::endl;
}
};
typedef Factory<Object> Singleton;
本類私有化了構造函數和析構函數,聲明瞭友元類Factory<Object>
, 並將其重命名爲 Singleton
下面看使用方法
int main(int , char *[])
{
Singleton::Instance()->dosomething();
return 0;
}
輸出
creator object
do something
destroy object
當然,模板單例還可以使用繼承的方法,繼承模板,實現模板單例,但這裏我將模板的構造函數私有化了,使其不可被繼承。並且,本例程 非線程安全 ,需要線程安全的可自行加鎖。
想要使用繼承的方法實現模板單例,網上很多,這裏就不再過多贅述了。