Singleton(單件)模型:一個類只有一個實例。
下面是C++代碼的單件模型:
Class Singleton
{
static Singleton s;
int i;
Singleton(int x):i(x){}
Singleton& operator=(Singleton&);//賦值操作符
Singleton(const Singleton&);//拷貝構造函數,防止被用戶調用,聲明為私有
public:
static Singleton& instance()
{return s;}//產生對象的引用
int getValue() {return i;}
void SetValue(int x)
{i = x;}
};
Singleton Singleton::s(47);
int main(){
Singleton& s= Singleton::instance();
cout << s.getvalue() <<endl;
Singleton& s2 = Singleton::instance()'
s2.setvalue(9);
cout<<s.getvalue()<<endl;
}
創建單件的關鍵是防止程序員控制對象的生存期的權利,所以構造函數,拷貝構造函數,賦值操作符都要聲明為私有(本例中沒有實現,因為賦值操作符和拷貝構造沒用到),并且防止編譯器產生任何缺省的構造函數。
要注意的是,這里的對象可以靜態創建,也可以知道程序員根據需求顯式創建,這個創建的方式又稱為lazy initialzation,這個做法只有在創建的對象的代價不大,并且不總是需要它的情況下才有意義。上面的這個方法并沒有限制只創建一個對象,支持創建有若干對象的對象池。如果遇到對象池中共享對象的問題,則可以對進出對象池的對象登記的方法解決。
類中的static靜態成員都是一個單件,從這個意義上說,編程語言提供了對單件的直接支持,但是如果一個對象依賴于一個對象時,對象的正確初始化就很重要了。下面是對上面的示例代碼的改進。
#include <iostream>
using namespace std;
class Singleton{
int i;
Singleton(int x):i(x){}
void operator=(Singleton&);
Singleton(const Singleton&);
public:
static Singleton& intstance(){
static Singleton s(45);
return s;
}
int getValue() {retrun 1;}
void setValue() {i = x;}
}
int maint()
{
Singleton& s= Singleton::instance();
cout<<s.getValue() <<endl;
Singleton s2=Singletonf::instance();
s2.setValue(9);
cout<<s.getValue<<endl;
}
下面是Scott Meyers兩個互相依賴的單間模型,由于是Scott Meyers創建,又稱Meyers單件。
Class Singleton1{
Singleton1(){}
public:
static Singleton1& ref
{
static Singleton1 single;
return single;
}
};
Class Singleton2{
Singleton1 &s1;
Singleton2(Singleton1& s):s1(s){}
public:
static Singleton2& ref()
{
static Singleton2 single(singleton1::ref));
return single;
}
Singleton1& f()
{return s1;};
int main()
{
Singleton1& s1 = Singleton2::ref().f();//導致惟一的Singleton2對象創建,Singleton2創建中,Singleton1::ref()被調用,導致Singleton1對象創建。
}
Singleton-ness是單件模型的變體:利用遞歸模板實現。
#include <iostream>
using namespace std;
template class Singleton
{
Singleton(const Singleton&);
Singleton& operator= (const Singleton&);
protected:
Singleton(){}
vitrual ~Singleton()
{}
public:
static T& instance()
{
static T theInstance;
return theInstance;
}
};
//Sample class to be made into a Singleton
Class MyClass:public Singleton
{
int x;
protected:
friend class Singleton;
MyClass()
{ x = 0;}
public:
void setValue(int n)
{x=n;}
int getVlalue()const
{return x;}
};
int main()
{
MyClass& m = MyClass::Instance();
cout << m.getValue()<<endl;
m.setValue(1);
cout << m.getValue()<<endl;
}
Singleton<MyClass>為友元;Singleton不依賴MyClass的大小,實際上這只是對模板參數的靜態依賴。只有當MyClass::Instance()被第一次調用時,才需要MyClass的大小。 單件模型實際應用的很少。