singleton
singleton即单件模式,实现这种模式的类在程序生命周期里只能有且仅有一个实例。单件模式是一个很有用的创建型模式,有许多实际的应用,并被广泛且深入地研究。
虽然单件模式非常重要,但很遗憾目前Boost中并没有专门的单件库,而仅是在serialization库中有一个并不十分完善的实现,它位于名字空间boost::serialization。
为了使用singleton,需要包含头文件<boost/serialization/singleton.hpp>,即:
#include <boost/serialization/singleton.hpp>
using boost::serialization::singleton;
类摘要
template <typename T>
class singleton : public boost::noncopyable
{
public:
static const T & get_const_instance();
static T & get_mutable_instance();
};
singleton把模板参数T实现为一个单件类,对类型T的要求是有缺省构造函数,而且在构造和析构时不能抛出异常,因为单件在main()前后构造和析构,如果发生异常则会无法捕获。
singleton提供两个静态成员函数访问单件实例,可分别获得常对象和可变对象。这种区分是出于线程安全的考虑,常对象单件总是线程安全的,因为它不会改变内部状态,而可变对象单件则不是线程安全的,可能会发生线程竞争问题。
用法
为了演示singleton的创建与销毁,下面的代码增加了构造函数与析构函数:
class point
{
public:
point(int a = 0, int b = 0, int c = 0) :x(a), y(b), z(c) //构造函数
{
cout << "point ctor" << endl;
}
~point() //析构函数
{
cout << "point dtor" << endl;
}
...
};
singleton的用法非常简单,只需要把想成为单件的类作为它的模板参数就可以了,接下来的工作由 singleton自动完成。可能唯一的一点不方便之处是过长的类型名,但可以用t ypedef来简化:
#include <boost/serialization/singleton.hpp>
using boost::serialization::singleton;
int main()
{
cout << "main() start" << endl;
typedef singleton<point> origin; //单件类定义
point::get_const_instance().print(); //常对象
point::get_mutable_instance().print(); //可变对象
cout << "main() finish" << endl;
}
代码中需要注意的是类名 singleton,还有就是访问实例的函数不是常用的instance(),而是get_const_instance()和 get_mutable_instance()。
除了这种模板方式,singleton还可以通过继承的方式来使用,把singleton作为单件类的基类,并把单件类作为singleton的模板参数:
#include <boost/serialization/singleton.hpp>
using boost::serialization::singleton;
class point : public singleton<point> //注意这里
{...}
int main()
{
cout << "main() start" << endl;
point::get_const_instance().print(); //常对象
point::get_mutable_instance().print(); //可变对象
cout << "main() finish" << endl;
}
这段代码与模板参数的用法仅有很小的不同,最重要的变化在于point类的基类声明处public继承singleton<point>
(如果读者不熟悉泛型编程,则可能会对这种父类中使用子类的形式有些困惑),因此point继承了singleton的所有能力,包括不可拷贝和单件。
与模板参数方式相比,继承方式实现单件模式更为彻底一些(很像noncopyable的用法),使被单件化的类成为了一个真正的单件类,而模板参数方式则更“温和”一些,它包装(wrap)了被单件化的类,对原始类没有任何影响。
代码示例
#include <iostream>
using namespace std;
#include <boost/serialization/singleton.hpp>
using boost::serialization::singleton;
//
class point : public singleton<point>
{
int x, y, z;
public:
point(int a = 0, int b = 0, int c = 0) :x(a), y(b), z(c)
{
cout << "point ctor" << endl;
}
~point()
{
cout << "point dtor" << endl;
}
void print()const
{
cout << x << "," << y << "," << z << endl;
}
};
typedef singleton<point> origin;
//
int main()
{
cout << "main() start" << endl;
origin::get_const_instance().print();
origin::get_mutable_instance().print();
point::get_const_instance().print();
point::get_mutable_instance().print();
cout << "main() finish" << endl;
}