[设计模式] -- 单例模式
Emai : hahayacoder@gmail.com
背景
最近在公司的项目中,经常会用到单例模式,由于之前没有想过怎么正确使用单例模式,导致写成的程序中有BUG。在学习Cocos2d-x时,导演类CCDirector等都是单例类。所以从头开始学习单例模式。
介绍
单例模式也称为单件模式,单子模式.使用单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有模块共享.有很多地方需要这样的功能模块,如系统的日志输出、人物管理器等。单例模式一般实现方式为:将类的构造函数定义成私有,定义一个私有的静态变量指针指向类得唯一实例,并提供一个公有静态方法获取该实例
简单实现
//Singleton.h#ifndef SINGLETON_H#define SINGLETON_Hclass Singleton{public: static Singleton* getInstance(); private: Singleton(); static Singleton* m_singleton;};#endif // SINGLETON_H//Singleton.cpp#include "singleton.h"#include <iostream>using namespace std;//static变量的定义Singleton* Singleton::m_singleton = NULL;Singleton* Singleton::getInstance(){ if(NULL == m_singleton) { m_singleton = new Singleton(); cout << "Singleton Create..." << endl; } return m_singleton;}Singleton::Singleton(){}//main.cpp#include "singleton.h"#include <QtCore/QCoreApplication>int main(int argc, char *argv[]){QCoreApplication a(argc, argv); Singleton *A = Singleton::getInstance(); Singleton *B = Singleton::getInstance(); return a.exec();}
运行结果:
从运行结果可以知道Singleton对象只创建了一次,即创建两个Singleton对象发现只打印出一次Create...即只调用了一次构造函数只生成了一个实例
深入思考
当在多线程中使用单例模式时(假设有A、B两个线程),同时调用getInstance函数,初始时m_singleton为NULL,当A线程调用getInstance时,执行到if(NULL==m_singleton)时,由于此时m_singleton为NULL,默认情况下是要执行if里面的语句,但是由于CPU时间片到了等原因,先要去执行B线程,B线程执行到if(NULL==m_singleton)时,此时m_singleton同样为NULL。这种情况下就会出现问题,下面使用Qt中的互斥锁重写代码
//Singleton.h#ifndef SINGLETON_H#define SINGLETON_H#include <QMutex>#include <QMutexLocker>class Singleton{public: static Singleton* getInstance();private: Singleton(); //定义静态成员 静态成员不属于某个对象 是属于整个类 static Singleton* m_singleton; static QMutex mutex;};#endif // SINGLETON_H//Singleton.cpp#include "singleton.h"#include <iostream>using namespace std;//static变量的定义QMutex Singleton::mutex;Singleton* Singleton::m_singleton = NULL;Singleton* Singleton::getInstance(){ //加锁 mutex.lock(); if(NULL == m_singleton) { m_singleton = new Singleton(); cout << "Singleton Create..." << endl; } //解锁 mutex.unlock(); return m_singleton;}Singleton::Singleton(){}