1.主旨
- 标准的单例模式考察过程,而在设计模式中单例模式可以分为“饿汉式”与“懒汉式”,对于这两种方式的具体讲解可以查看我之前的文章设计模式学习(一) 单例模式 Singleton。在此之外,单例模式构建的同时还需要考虑多线程以及优化方面的考虑,所以这里参照书上的例子,实现了四种格式的单例模式。
2.考点
- 考点1:单例模式的基本单线程实现,包括饿汉式与懒汉式;
- 考点2:单例模式的基本多线程实现,主要是new前后加锁,与加锁的判断条件;
- 考点3:单例模式如何通过嵌套类实现;(针对C++,无静态构造函数)
3.代码
#include <iostream>
#include <mutex>
using namespace std;
class Singleton
{
public:
void Free() {};
};
3.1 普通单线程懒汉式Singleton1
- 懒汉式即在被调用getInstance时才会被构建
class Singleton1 : public Singleton
{
public:
static Singleton1* getInstance()
{
if (m_self == nullptr)
m_self = new Singleton1();
return m_self;
}
void Free()
{
if (m_self != nullptr)
{
delete m_self;
m_self = nullptr;
}
}
private:
static Singleton1* m_self;
};
Singleton1* Singleton1::m_self = nullptr;
3.2 普通单线程饿汉式Singleton2
- 饿汉式即在全局/静态变量初始化时,就已经将对象构建了
class Singleton2 : public Singleton
{
public:
static Singleton2* getInstance()
{
return m_self;
}
void Free()
{
if (m_self != nullptr)
{
delete m_self;
m_self = nullptr;
}
}
private:
static Singleton2* m_self;
};
Singleton2* Singleton2::m_self = new Singleton2();
3.3 改进多线程饿汉式Singleton3
- 在new操作前后加了mutex锁(多线程互斥),并判断了加锁条件(减少内存消耗)
mutex g3_lock;
class Singleton3 : public Singleton
{
public:
static Singleton3* getInstance()
{
if (m_self == nullptr)
{
g3_lock.lock();
if (m_self == nullptr)
m_self = new Singleton3();
g3_lock.unlock();
}
return m_self;
}
void Free()
{
if (m_self != nullptr)
{
delete m_self;
m_self = nullptr;
}
}
private:
static Singleton3* m_self;
};
Singleton3* Singleton3::m_self = nullptr;
3.4 高级多线程懒汉式单例Singleton4
- 单例的构建过程为包含了锁与判断条件的懒汉式单例模式,但是其构建流程为通过内部类innerSingleton的函数getInstance来实现,其将Singleton4进行new出后再返回出来。与其他的单例相比,其最大的区别是没有自己的成员变量,而是在自己的内部类的成员变量中。
- PS:此类是参照书上的按需创建实例来写的,但是书上这种写法是对应C#的静态构造函数来实现的,本文中参照的是传统的懒汉式写法,其本身就具备在被调用时才会被创建的特性,所以单例Singleton4可能就只是Singleton3换了身衣服吧哈哈。
mutex g4_lock;
class Singleton4 : public Singleton
{
public:
static Singleton4* getInstance()
{
return innerSingleton::getInstance();
}
class innerSingleton
{
public:
static Singleton4* getInstance()
{
if (m_self == nullptr)
{
g4_lock.lock();
if (m_self == nullptr)
m_self = new Singleton4();
g4_lock.unlock();
}
return m_self;
}
static Singleton4* m_self;
};
void Free()
{
if (innerSingleton::m_self != nullptr)
{
delete innerSingleton::m_self;
innerSingleton::m_self = nullptr;
}
}
};
Singleton4* Singleton4::innerSingleton::m_self = nullptr;
3.5 测试用主函数
int main()
{
Singleton* temp1;
Singleton* temp2;
int num = 4;
switch (num)
{
case 1:
{
temp1 = Singleton1::getInstance();
temp2 = Singleton1::getInstance();
break;
}
case 2:
{
temp1 = Singleton2::getInstance();
temp2 = Singleton2::getInstance();
break;
}
case 3:
{
temp1 = Singleton3::getInstance();
temp2 = Singleton3::getInstance();
break;
}
case 4:
{
temp1 = Singleton4::getInstance();
temp2 = Singleton4::getInstance();
break;
}
default:
{
temp1 = Singleton1::getInstance();
temp2 = Singleton1::getInstance();
break;
}
}
if(temp1 == nullptr && temp2 == nullptr)
cout << "temp1与temp2此时均未初始化" << endl;
if(temp1 != nullptr && temp2 != nullptr)
cout << "temp1与temp2此时均已被初始化" << endl;
if (temp1 == temp2)
cout << "Singleton" << num << "相同" << endl;
else
cout << "Singleton" << num << "不相同" << endl;
temp1->Free();
temp2->Free();
return 0;
}