#include <iostream>
namespace ImplMethod1 {
//Singleton template implementation: Method 1
template <typename T>
class Singleton {
public:
static T* GetInstance() {
//You can consider thread-safe here if you will
static T* s_ptr = new T;
return s_ptr;
}
private:
Singleton() {};
virtual ~Singleton() {};
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};
//How use it
class MyClass {
public:
void func() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
private:
friend class Singleton<MyClass>;
MyClass() {};
~MyClass() {};
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
};
} // end of namespace ImplMethod1
//---------------------------------------------------------------------------
namespace ImplMethod2 {
//Singleton template implementation: Method 2
template <typename T>
class Singleton {
public:
static T* GetInstance() {
//You can consider thread-safe here if you will
static T* s_ptr = new T;
return s_ptr;
}
protected:
Singleton() {};
virtual ~Singleton() {};
private:
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};
//How use it
class MyClass: public Singleton<MyClass> {
public:
void func() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
private:
friend class Singleton<MyClass>;
MyClass() {};
~MyClass() {};
};
} // end of namespace ImplMethod2
//---------------------------------------------------------------------------
namespace ImplMethod3 {
//Singleton template implementation: Method 3
class LazyInstantiation {
protected:
template <typename T>
static T* CreateInstance(T* dummy) {
//You can consider thread-safe here if you will
return new T;
}
virtual ~LazyInstantiation() {};
};
template <typename T, typename InstantiationPolicy = LazyInstantiation>
class Singleton : public InstantiationPolicy {
public:
static T* GetInstance() {
//You can consider thread-safe here if you will
static T* s_ptr = InstantiationPolicy::CreateInstance((T*)NULL);
return s_ptr;
}
protected:
Singleton() {};
virtual ~Singleton() {};
private:
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
};
//How use it
class MyClass: public Singleton<MyClass> {
public:
void func() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
private:
friend class LazyInstantiation;
MyClass() {};
~MyClass() {};
};
} // end of namespace ImplMethod3
//---------------------------------------------------------------------------
/**
* 分析:
* 方法1不需要繼承,但不能直觀的通過MyClass::GetInstance來獲取實例,且在MyClass里需要將拷貝構造以及operator=聲明為private;
* 方法2通過繼承的方式,比方法1好;
* 方法3在方法2的基礎上,進行了巧妙的擴展,可以讓用戶自定InstantiationPolicy,可以支持一些有特殊構造函數的類;
*
* 結論:
* 綜合來看,方法2簡單易用,方法3實現成本稍高,但比方法2又精進了一步。
*/
int main(int argc, char* argv[]) {
ImplMethod1::MyClass* p1 = ImplMethod1::Singleton<ImplMethod1::MyClass>::GetInstance();
p1->func();
ImplMethod2::MyClass* p2 = ImplMethod2::MyClass::GetInstance();
p2->func();
ImplMethod3::MyClass* p3 = ImplMethod3::MyClass::GetInstance();
p3->func();
return 0;
}