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的大小。 单件模型实际应用的很少。