设计模式之单例(C++版)
单例是一种常见的设计模式,用来表示一个系统中存在的独立并且唯一的对象实例,比如一个绘图的对象,维护列表的对象,等等。单例其实是模拟了C语言中的全局变量的作用,但是要比它更健壮安全。我们先看一个C++版的单例
#ifndef SINGLETON_H_ #define SINGLETON_H_ #include <stdio.h> template<typename T> class Singleton { public: static T * Instance() { if (_instance == NULL) { _instance = new T(); } return _instance; } protected: Singleton(){} private: static T* _instance; }; template<typename T> T* Singleton<T>::_instance = NULL; #endif
首先,我们定义了一个类模板,怎样从这个模板得到单例对象呢?很简单,只需要从这个类派生出一个子类,像下边这样
class AppList:public Singleton<AppList> { private: AppList(){} friend class Singleton<AppList>; public:
...
int getCount(){return 5;}
};
这样可以这么引用
... int n = AppList::Instance()->getApCount(); ...
使用起来还是很方便的。
接下来我们探讨一下技术实现。
从类模板开始,为了实现通用的单例算法,这里使用了模板,好处就不多说了,大部分的算法都会采用这种方式的(当然模板也有缺点的)。
这个模板是怎么样保证单例的?主要是通过以下几个要点,
在模板中将构造函数声明为protected。访问属性声明为protected的函数(或方法),只有类内部或者派生类内部才能访问,当我们用 A *a = new A();或者A a;这种常见的方式来实例化对象时,编译器检测到这个类的构造函数是带保护属性的,不能被对象访问,就会拒绝为该类产生实例,这样,也就避免了直接创建实例的可能。
在模板中声明一个私有静态的实例对象的指针作为唯一对象的引用,由于这个指针是私有的,不能被外界访问和操作,于是在模板中提供了一个public 的静态方法Instance()来初始化并返回这个对象指针,注意,因为不能直接初始化对象实例,只能从这个函数得到一个唯一实例的指针,所有对这个类方法的访问只能通过这个接口,这就是单例模式。
从派生类实例对象。直接从类模板得到的单例是没用的,因为它不包含其他数据。所以我们可以在类模板的基础上,创建一个派生类,把数据放到派生类里边。将派生类的构造函数设置为私有,强化了派生类的单例特性。这里的友元函数是为了让派生类能够访问父类提供的静态方法。
上面的单例技术,在多线程的时候并不是很安全,如果是在这种情况下,需要加锁以及多次判断等技巧,若有高手可以阐述一下。

浙公网安备 33010602011771号