C++单例模式的六种实现

                                    (如有错误,请联系我更正,以免误导他人!)

       C++中单例模式的应用非常广泛,在我们平时使用的windows操作系统中就存在大量的单例应用。如:回收站、任务管理器、文件资源管理器等。

       单例模式的实现也有许许多多的方法,每种实现方法都有各自的优点和实用场景。

实现一:

class Singleton {
public:
	static Singleton* getInstance();
	~Singleton();
private:
	Singleton();
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
private:
	static Singleton* m_Instance;
};
Singleton* Singleton::m_Instance = nullptr;
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
	if (m_Instance == nullptr)
		m_Instance = new Singleton;
	return m_Instance;
}


分析

       优点:1、实例在首次调用getInstance时才创建

       缺点:1、程序结束时析构函数不被调用,需要手动delete释放内存并关闭/恢复类中操作(主要是程序结束后还是不被关闭的操作,如:数据库连接、文件锁、注册表操作)

       2、线程不安全,在多线程情况下可能会产生多个实例(下面是break在QQ刚登入没多久时查看的线程数,82个。。。试想如果82个线程同时调用getInstance)

实现二:在实现一的基础上修改getInstance函数如下:

Singleton* Singleton::getInstance() {
	if (m_Instance == nullptr)
	{
		Lock();//线程锁
		if (m_Instance == nullptr)
			m_Instance = new Singleton;
		UnLock();
	}
	return m_Instance;
}

分析

       在实现一的基础上解决了线程不安全问题,但加锁操作使程序在性能上有所下降(当数据量大的时候不推荐使用)

实现三:

class Singleton {
public:
	static Singleton* getInstance();
	~Singleton();
private:
	Singleton();
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
};
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
	static Singleton m_Instance;
	return &m_Instance;
}

分析

       使用了局部静态变量。在实现二的基础上解决了性能下降的问题,但实例只能在程序结束时销毁,从程序开始到程序结束一直占用内存。换一种思考方式,相对于前面两种实现,实现三能够省去程序员的维护工作,不用手动delete释放内存。

实现四:

class Singleton {
public:
	static Singleton* getInstance();
	~Singleton();
private:
	Singleton();
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
	static Singleton m_Instance;
};
Singleton Singleton::m_Instance;
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
	return &m_Instance;
}

分析

       与实现三相比,实现四中实例为静态成员变量,在程序的开始初始化。

实现五:

class Singleton {
public:
	static Singleton* getInstance();
	static void destoryInstance();
private:
	~Singleton();
	Singleton();
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
	static Singleton* const m_Instance;
};
Singleton* const Singleton::m_Instance=new Singleton;
Singleton::Singleton() {}
Singleton::~Singleton() {}
void Singleton::destoryInstance() {
	if (m_Instance != nullptr)
	{
		delete m_Instance;
		const_cast(m_Instance) = nullptr;
	}
}
Singleton* Singleton::getInstance() {
	return m_Instance;
}

分析

       实例在程序开始初始化,避免了实现一中的线程不安全问题。同实现一、二,相对于实现三、四而言,我们需要手动释放内存。

实现六:

class Singleton {
public:
	static Singleton* getInstance();
	static void destoryInstance();
private:
	~Singleton();
	Singleton();
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
private:
	class GC {
	public:
		~GC()
		{
			destoryInstance();
		}
	};
private:
	static Singleton* const m_Instance;
	static GC gc;
};
Singleton* const Singleton::m_Instance = new Singleton;
Singleton::GC Singleton::gc;
Singleton::Singleton() {}
Singleton::~Singleton() {}
void Singleton::destoryInstance() {
	if (m_Instance != nullptr)
	{
		delete m_Instance;
		const_cast(m_Instance) = nullptr;
	}
}
Singleton* Singleton::getInstance() {
	return m_Instance;
}

分析

       在实现五的基础上添加了私有内部类GC,创建了私有静态成员变量gc。这里利用了C++的RALL机制。当程序结束时,通过释放静态成员变量gc来释放单例m_Instance,并在单例的析构中做一些对类中其他操作的释放。这里相对于实现五来说添加了实现三、四具备的自动回收机制。利用实现六,我们可以在需要释放的时候手动释放单例,也可以让程序在结束时自动回收单例(防止程序员忘记释放内存,就像我们平时忘记delete一样)。我们在实现一个有很多不可预料的因素的功能时,这么做是很有帮助的,我们可以通过对不可预测的因素进行if判断来决定是否提前释放单例。


       可见单例模式的实现多种多样,各有千秋。我们需要根据功能需求来选择合适我们的实现方法


       如果有更多更好的单例模式实现方法,小伙伴们不妨拿出来分享一下,谢谢啦!



你可能感兴趣的:(设计模式,C++学习笔记)