设计模式之单例模式

来源:互联网 发布:一点一点吃干抹净淘宝 编辑:程序博客网 时间:2024/06/05 17:19

设计模式在面试中单例模式应该是被问到最多的吧,记得前段时间找实习的时候就被问到了,面试官问我单例模式要不要析构函数,我当时回答的要,下来之后就恶补了一下关于单例模式这方面的东西,也看了许多大神写的博客,下面写一写我自己对于单例模式的一些薄见吧

单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点

也就是说一个类只能创建一个实例来,在类外不可以多次对它创建实例,因为我们都知道类是通过构造函数来创建对象的,如果要类外不可以创建对象,那么就是要类外不能访问类的构造函数。那么我们可以写出单例第一版出来,也是最简单的一个版本

#include<iostream>using namespace std;//方法一:使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态方法获取该实例class Singleton{public:static Singleton* getInstall(){if (m_instance == NULL){m_instance = new Singleton();}return m_instance;}private://构造函数私有化Singleton(){}static  Singleton* m_instance;};Singleton* Singleton::m_instance = NULL;int main(void){Singleton* p1 = Singleton::getInstall();//Singleton* p2 = p1->getInstall();Singleton* p2 = Singleton::getInstall();if (p1 == p2){cout << "equal" << endl;}else{cout << "not equal" << endl;}return 0;}
在这里将构造函数私有化,利用一个静态函数来创建变量。但是这里有一个问题就是在多线程的情况下,它是不安全的。我们知道在多线程的情况下我们可以通过加锁机制来控制线程安全,那么我们可以写出第二版代码
#include<iostream>using namespace std;class Singleton{public:static Singleton* getInstall(){if (m_instance == NULL){//加锁lock();  //C++没有直接的Lock操作,请使用其它库的Lock,比如Boost,此处仅为了说明if (m_instance == NULL){m_instance = new Singleton();}//解锁unlock();}return m_instance;}private://构造函数私有化Singleton(){}static  Singleton* m_instance;};Singleton* Singleton::m_instance = NULL;int main(void){Singleton* p1 = Singleton::getInstall();//Singleton* p2 = p1->getInstall();Singleton* p2 = Singleton::getInstall();if (p1 == p2){cout << "equal" << endl;}else{cout << "not equal" << endl;}return 0;}
这里运用了锁机制实现了线程安全的,但是呢,又出现了一个问题就是new出来的对象,在什么时候释放掉呢,这是一个问题。我们知道在程序结束的时候系统会释放掉所有全局变量的内存,系统也会析构所有类的静态成员变量,利用这个特性,我们可以在类中定义一个静态全局变量,它的唯一作用就是释放掉new开辟出来的资源

#include<iostream>using namespace std;class Singleton{public:static Singleton* getInstall(){if (m_instance == NULL){//加锁//lock();if (m_instance == NULL){m_instance = new Singleton();}//解锁//unlock();}return m_instance;}private://构造函数私有化Singleton(){}static  Singleton* m_instance;class Garbo{public:Garbo(){if (Singleton::m_instance != NULL){delete Singleton::m_instance;}}};static Garbo garbo;};Singleton* Singleton::m_instance = NULL;int main(void){Singleton* p1 = Singleton::getInstall();//Singleton* p2 = p1->getInstall();Singleton* p2 = Singleton::getInstall();if (p1 == p2){cout << "equal" << endl;}else{cout << "not equal" << endl;}return 0;}
这里任然运用了加锁机制,但是在大数据的计算中,加锁会成为影响性能的主要原因,所以这里我们得把这个锁去掉,那么就可以用空间换时间的方法来进行改进,在最开始还没进入主程序之前就创建好一个唯一的实例,然后每次都是调用这一个实例。也就是饿汉模式

#include<iostream>using namespace std;class Singleton{public:static const Singleton* getInstall(){return m_instance;}private://构造函数私有化Singleton(){}static const Singleton* m_instance;class Garbo{public:Garbo(){if (Singleton::m_instance != NULL){delete Singleton::m_instance;}}};static Garbo garbo;};const Singleton* Singleton::m_instance = new Singleton();int main(void){const Singleton* p1 = Singleton::getInstall();//Singleton* p2 = p1->getInstall();const Singleton* p2 = Singleton::getInstall();if (p1 == p2){cout << "equal" << endl;}else{cout << "not equal" << endl;}return 0;}
这里const的作用是保证实例不会被改变

static的作用是保证它进入主函数之前就被初始化了

上面是我自己的一些看法,希望可以和大家多交流交流,可以多指点我!