虽然不是在设计模式中看得第一个模式,但是这是第一个写博客的模式,之前的学习的工厂模式后续再写,这是一个不简单的设计模式,再我看过的设计模式中单例模式虽然没有把面向对象的三大特性全部表现出来。但是,我感觉依然还是不容易理解的。接下来言归正传,说一下单例模式。
单例模式必须保证一个类只能生成一个实例。并提供一个全局的访问点,该实例是被所有的程序所共享的。也就是说在使用这个类是只能有一个对象产生,就像一个全局变量一样,每个程序都可以使用这个变量。所以,Singleton类的创建和销毁需要类本身完成。在c++中,它的构造函数和析构函数是不能被公开调用的。
由于Singleton类的对象的创建时间不同,模式也不相同,分为:懒汉模式和饿汉模式。
懒汉模式:
//懒汉模式--用指针实现
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
if(instance == NULL)
instance = new Singleton();
return instance;
}
private:
Singleton(){}
Singleton(const Singleton&){}
Singleton& operator=(const Singleton&){}
~Singleton()
{
cout << "析构函数" << endl;
}
private:
static Singleton* instance;
};
Singleton* Singleton::instance = NULL;
int main()
{
Singleton* sing1 = Singleton::getInstance();
Singleton* sing2 = Singleton::getInstance();
if(sing1 == sing2)
cout << "sing1 == sing2" << endl;
return 0;
}
然而,但多线程时,此例是不安全的。例如,当线程A进入判断之后,被线程B中断,从而执行线程B,执行完线程B之后再执行线程A,会使得线程A的条件发生变化,然而还不能再次判断。就会再次创建一个对象,从而就不在是单例模式了。同时,此例没有析构,可能会存在内存泄漏,然而,我看到一篇博客说,静态指针是不会存在内存泄漏的,它会根据程序的退出,操作系统会清除所有的内存空间。
//懒汉模式--局部静态变量
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
private:
Singleton(){}
Singleton(const Singleton&){}
Singleton& operator=(const Singleton&){}
~Singleton(){}
};
int main()
{
Singleton* sing1 = Singleton::getInstance();
Singleton* sing2 = Singleton::getInstance();
if(sing1 == sing2)
cout << "sing1 == sing2" << endl;
return 0;
}
其实,局部静态初始化对象,线程也是不安全的的。如果初始化时有多条语句,就会使得出现多线程竞争问题。
饿汉模式的单例模式是在主函数之前定义了一个全局变量,出现的时间比较早。
//饿汉模式--局部静态变量
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton& getInstance();
private:
Singleton(){}
Singleton(const Singleton&){}
Singleton& operator=(const Singleton&){}
~Singleton(){}
private:
static Singleton m_instance;
};
Singleton Singleton::m_instance;
Singleton& Singleton::getInstance()
{
return m_instance;
}
int main()
{
Singleton& sing1 = Singleton::getInstance();
Singleton& sing2 = Singleton::getInstance();
if(&sing1 == &sing2)
cout << "sing1 == sing2" << endl;
return 0;
}
饿汉模式是用空间换时间,在类外定义一个全局变量会浪费空间,但是实现简单,对于多线程也是安全的。
//饿汉模式--局部静态变量
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance();
private:
Singleton(){}
Singleton(const Singleton&){}
Singleton& operator=(const Singleton&){}
~Singleton(){}
private:
static Singleton *m_instance;
};
Singleton* Singleton::m_instance = new Singleton();
Singleton* Singleton::getInstance()
{
return m_instance;
}
int main()
{
Singleton* sing1 = Singleton::getInstance();
Singleton* sing2 = Singleton::getInstance();
if(sing1 == sing2)
cout << "sing1 == sing2" <<endl;
return 0;
}