设计模式之单例模式

一、单例模式的概念

单例模式是一种对象创建型模式, 使用单例模式, 可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。

二、单例模式使用场景

在软件开发中,我们常常有以下需求:
1、在多个线程之间,共享同一个资源或者操作同一个对象。
2、 在整个程序空间使用全局变量,共享资源。
3、大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。

单例模式可以保证为一个类只生成唯一的实例对象,上面这些场景中就可以使用单例模式了,单例模式也是软件开发中最常使用的设计模式。

三、单例模式构建方法

1、 必须提供一个私有化的构造函数,以防止二次实例化对象。
2、必须提供一个全局的静态方法,以便外界访问调用。
3、在类中定义一个静态指针,指向本类的变量的静态变量指针。

四、单例模式的示例

1、个人最常用的一种单例模式构建方法

#include <iostream>

class Singleton
{
public:
	// 提供一个全局的访问入口,注意返回值是静态指针
	static Singleton *GetInstance()
	{
		// 定义一个本类的静态变量
		static Singleton instance;
		return &instance;
	}

	void printSelf()
	{
		std::cout << "Hello! I'm Singleton Pattern\n";
	}

private:
	// 构造函数私有化
	Singleton() {};
};

int main()
{
	Singleton::GetInstance()->printSelf();
	getchar();
}

上面的这种构建单例的方法是最简单、最方便的方法,不用担心线程安全、内存释放问题、也不用担心出现类拷贝问题,这也是我最钟爱的实现单例的方法。

2、懒/饿汉式单例
1)代码示例

#include <iostream>
#include <mutex>
using namespace std;

// 懒/饿汉式单例公用部分
class Singleton
{
public:

	// 提供一个全局的访问入口
	static Singleton *GetInstance();

	void printSelf()
	{
		std::cout << "Hello! I'm Singleton Pattern\n";
	}

	// 释放内存
	static void DestoryInstance() 
	{ 
		if (m_pSingleton != nullptr)
		{ 
			delete m_pSingleton; 
			m_pSingleton = nullptr;
		} 
	}

private:
	// 构造函数私有化
	Singleton() {};
	// 定义一个本类的静态变量
	static Singleton *m_pSingleton;
	static mutex m_mutex;
};

// 懒汉式单例
Singleton *Singleton::m_pSingleton = nullptr;
Singleton *Singleton::GetInstance()
{
	if (m_pSingleton == nullptr)
	{
		// 为保证单例在多线程中安全加锁
		lock_guard<mutex> tmpLock(m_mutex);
		if (m_pSingleton == nullptr)
		{
			m_pSingleton = new Singleton;
		}
	}
	return m_pSingleton;
}

//饿汉式单例
Singleton *Singleton::m_pSingleton = new Singleton();
Singleton *Singleton::GetInstance()
{
	return m_pSingleton; 
}

int main()
{
	Singleton::GetInstance()->printSelf();
//主动释放内存
	Singleton::GetInstance()->DestoryInstance();
	getchar();
}

2)懒汉式和饿汉式的优缺点
懒汉式
优点:每次使用时才初始化。
缺点:为保证多线程安全需要加锁,损失了性能。

饿汉式
优点:多线程安全,无需加锁。
缺点:类加载时就初始化,浪费内存。

3)懒汉式和饿汉式的内存释放问题
无论懒汉还是饿汉式都需要释放内存,主动释放内存就像上面的示例种实现的DestoryInstance()函数那样,写一个主动释放内存的函数去释放内存。还有一种垃圾回收机制就是在单例中写一个垃圾回收类,来自动实现内存的释放。

// 可以在Singleton类中垃圾回收类

class ClearRubbish
{
	public: ~ClearRubbish() 
	{ 
		// 释放所有的资源 
		if (m_pSingleton != nullptr)
		{ 
			cout << "destory all source..." << endl; 
			delete m_pSingleton; 
			m_pSingleton = nullptr;
		} 
	}
static ClearRubbish CR; // 用于释放单例 
};

Singleton::ClearRubbish Singleton::ClearRubbish::CR; // 声明一下就可以自动释放垃圾

五、留个思考?

为什么不在单例的析构函数中销毁单例的静态指针呢?

如有错误,欢迎指正。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值