1、单例模式简介
单例模式通过维护一个static的成员变量来记录这个唯一的对象实例,通过提供一个static的接口instance来获取唯一的实例。关系图
2、示例
本文使用的实例均摘自网络,在此处只是整理工作
1)单例模式代码示例(一):最简单的单例模式
//Singleton1.h
#ifndef __Singleton__Singleton1__
#define __Singleton__Singleton1__
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
if(m_Instance == NULL)
{
m_Instance = new Singleton();
}
return m_Instance;
};
static void DestoryInstance()
{
if(m_Instance != NULL)
{
delete m_Instance;
m_Instance = NULL;
}
}
int getTest()
{
return m_Test;
}
private:
Singleton() {m_Test = 10;}
static Singleton* m_Instance;
int m_Test;
};
#endif /* defined(__Singleton__Singleton1__) */
//main.cpp
#include "Singleton1.h"
#include <iostream>
Singleton* Singleton::m_Instance = NULL;
int main(int argc, const char * argv[]) {
// insert code here...
Singleton* single = Singleton::getInstance();
cout << single->getTest() << endl;
return 0;
}
打印结果
这是最简单也是最普遍的实现方式,但是这种方式没有考虑到多线程的问题,在多线程的情况下,可能创建多个Singleton实例。
2)单例模式代码示例(二):示例(一)改善的代码
#ifndef __Singleton__Singleton2__
#define __Singleton__Singleton2__
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
if(m_Instance == NULL)
{
// Lock();//C++没有直接的Lock操作,可以使用其他库的Lock,比如Boost,此处仅说明
if(m_Instance == NULL)
{
m_Instance = new Singleton();
}
// UnLock();//C++没有直接的Lock操作,可以使用其他库的Lock,比如Boost,此处仅说明
}
return m_Instance;
};
static void DestoryInstance()
{
if (m_Instance != NULL)
{
delete m_Instance;
m_Instance = NULL;
}
}
int getTest()
{
return m_Test;
}
private:
Singleton(){m_Test = 0;}
static Singleton* m_Instance;
int m_Test;
};
#endif /* defined(__Singleton__Singleton2__) */
此处进行了两次m_Instance == NULL的判断,是借鉴了Java的单例模式实现时,使用的所谓“双检锁”机制,因为进行一次加锁和解锁需要付出对应的代价,而进行两次判断,就可以避免多次加锁与解锁操作,同时也保证了线程安全,但是如果在大数据操作的项目中,加锁操作将成为一个性能的瓶颈,下面就出现了第三种单例代码。
3)单例模式代码示例(三)
//Singleton.h
#ifndef __Singleton__Singleton3__
#define __Singleton__Singleton3__
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
return const_cast<Singleton*>(m_Instance);
}
static void DestoryInstance()
{
if(m_Instance != NULL)
{
delete m_Instance;
m_Instance = NULL;
}
}
int getTest()
{
return m_Test;
}
private:
Singleton() {m_Test = 10;}
<span style="color:#cc0000;">static const Singleton* m_Instance;
</span> int m_Test;
};
#endif /* defined(__Singleton__Singleton3__) */
//main.cpp
#include "Singleton3.h"
#include <iostream>
<span style="color:#cc0000;">const Singleton* Singleton::m_Instance = new Singleton();
</span>
int main(int argc, const char * argv[]) {
// insert code here...
Singleton* single = Singleton::getInstance();
cout << single->getTest() << endl;
return 0;
}
因为静态初始化在程序开始时,也就是进入主函数之前,由于主线程以单线程方式完成初始化,所以静态初始化实例保证了线程安全性,在性能要求较高时,就可以使用这种方式,从而避免频繁的加锁解锁造成的资源浪费,但是该方法没有实现实例的销毁。下面出现了示例(四)
4)单例模式代码示例(四)
//Singleton4.h
#ifndef __Singleton__Singleton4__
#define __Singleton__Singleton4__
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
static Singleton m_Instance;
return &m_Instance;
}
int getTest()
{
return m_Test;
}
private:
Singleton() {m_Test = 10;}
int m_Test;
};
#endif /* defined(__Singleton__Singleton4__) */
//main.cpp
#include "Singleton4.h"
#include <iostream>
int main(int argc, const char * argv[]) {
// insert code here...
Singleton* single = Singleton::getInstance();
cout << single->getTest() << endl;
return 0;
}
5)单例模式代码示例(五)
//Singleton.h
#ifndef __Singleton__Singleton__
#define __Singleton__Singleton__
#include <iostream>
using std::cout;
using std::endl;
using std::string;
class Singleton
{
public:
static Singleton* getInstance()
{
if(m_Instance == NULL)
{
m_Instance = new Singleton();
}
return m_Instance;
}
int getTest()
{
return m_Test;
}
private:
Singleton() {m_Test = 10;}
static Singleton* m_Instance;
int m_Test;
class GC
{
public:
~GC()
{
if(m_Instance != NULL)
{
cout << "Here is the test" << endl;
delete m_Instance;
m_Instance = NULL;
}
}
};
static GC gc;
};
#endif /* defined(__Singleton__Singleton__) */
//使用在main.cpp中
//main.cpp
#include "Singleton.h"
#include <iostream>
Singleton* Singleton::m_Instance = NULL;
Singleton::GC Singleton::gc;
int main(int argc, const char * argv[]) {
// insert code here...
Singleton* single = Singleton::getInstance();
cout << single->getTest() << endl;
return 0;
}
打印结果
在程序运行结束时,系统会调用Singleton的静态成员GC的析构函数,该析构函数会进行资源的释放,而这种资源的释放方式是在我们不知情的情况下进行的。原因是:由于程序在结束的时候,系统会自动析构所有的全局变量,实际上系统也会析构所有类的静态成员变量,静态变量和全局变量一样,存储在静态存储区,所以析构时是同等对待的。此方法是借助一个内部GC类,来释放资源。要熟练使用这种技巧。