模式意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
要点
某个类只能有一个实例;
它必须自行创建这个实例;
它必须自行向整个系统提供这个实例。
工作原理
用一个特殊方法来实例化所需的对象。
调用这个方法时,检查对象是否已经实例化。若已经实例化,该方法仅返回对该对象的一个引用。若未实力哈,该方法实例化该对象并返回对此新实例的一个引用。
为了确保这是实例化此类型对象的唯一方法,将这个类的构造函数定义为保护或者私有的。
使用步骤
构造函数私有化;
提供一个全局的静态方法(全局访问点)来获取单例对象;
在类中定义一个静态指针,指向本类的变量的静态变量指针。
懒汉模式
class singleton {
public:
static singleton* getInstance() {
if (instance == NULL) {
instance = new singleton;
}
return instance;
}
private:
/*不让类的外部再创建实例*/
singleton() {
cout << "singleton" << endl;
}
private:
/*指向本类唯一实例的指针*/
static singleton *instance;
};
singleton* singleton::instance = NULL;
int main(int argc, char **argv)
{
cout << "main" << endl;
singleton *sig = singleton::getInstance();
return 0;
}
当懒汉式遇见多线程时,需要利用加锁解锁机制,在对instance变量判断是否为空时之前加锁,防止多个线程同时判断是为空,返回2个new,违背了单例模式。
饿汉式
/*饿汉式-------在编译期间就已经确定该对象的唯一实例*/
class singleton {
public:
static singleton* getInstance() {
return instance;
}
private:
/*不让类的外部再创建实例*/
singleton() {
cout << "singleton" << endl;
}
private:
/*指向本类唯一实例的指针*/
static singleton *instance;
};
singleton* singleton::instance = new singleton;
int main(int argc, char **argv)
{
cout << "main" << endl;
singleton *sig1 = singleton::getInstance();
singleton *sig2 = singleton::getInstance();
if (sig1 == sig2) {
cout << "The same instance" << endl;
}
return 0;
}
单例模式的优缺点
优点
单例模式提供了对唯一实例的受控访问;
节约系统资源。只存在一个对象。
缺点
扩展略难。单例模式中没有抽象层;
单例类的职责过重。
适用场景
系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或者资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象;
客户调用类的单个实例只允许适用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。