【剑指offer】面试题2 单例模式Singleton

1.主旨

  • 标准的单例模式考察过程,而在设计模式中单例模式可以分为“饿汉式”与“懒汉式”,对于这两种方式的具体讲解可以查看我之前的文章设计模式学习(一) 单例模式 Singleton。在此之外,单例模式构建的同时还需要考虑多线程以及优化方面的考虑,所以这里参照书上的例子,实现了四种格式的单例模式。

2.考点

  • 考点1:单例模式的基本单线程实现,包括饿汉式与懒汉式;
  • 考点2:单例模式的基本多线程实现,主要是new前后加锁,与加锁的判断条件;
  • 考点3:单例模式如何通过嵌套类实现;(针对C++,无静态构造函数)

3.代码

  • 所用头文件以及一个随意的基类Singleton
#include <iostream>
#include <mutex>
using namespace std;

class Singleton
{
public:
	void Free() {};
};
3.1 普通单线程懒汉式Singleton1
  • 懒汉式即在被调用getInstance时才会被构建
//1.普通的懒汉式单例Singleton1,类外初始化
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
  • 饿汉式即在全局/静态变量初始化时,就已经将对象构建了
//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锁(多线程互斥),并判断了加锁条件(减少内存消耗)
//3.改进的懒汉式单例Singleton3,类外初始化,getInstance锁,条件判断是否加锁
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换了身衣服吧哈哈。
//4.高级的懒汉式单例Singleton4,类外初始化,getInstance锁,条件判断是否加锁,条件创建实例(类包类)
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 测试用主函数
  • 用一个很随意的swtich case语句写的。
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值