C++07设计模式之单例模式

1.设计模式

设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码 可靠性。
设计模式代表了最佳的实践,是软件开发人员在软件开发过程中面临的一般问题 的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和 错误总结出来的。

1.1什么是单例模式

1.保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2.单例模式,顾名思义,即单个实例的模式。既然是面向对象,那么一个类只允许 产生一个实例对象的话,就是单例模式。类对象有且只有一个,任何使用该类的人在不改变源码的前提下都不能生成第二 个对象。单例模式就是一个类只能被实例化一次 ,更准确的说是只能有一个实例 化的对象的类。
3.单例模式的标准定义:单例模式确保某一个类只有一个实例,而且自行实例化并 向整个操作系统提供这个实例,这个类成为单例类,它提供全局的访问方法。
4.单例模式的三个要点:
• 单例类只能有一个实例
• 它必须自行创建这个实例
• 它必须自行向整个系统提供提供这个实例
从具体实现角度来说,就是以下三点:
• 单例模式的类只提供私有的构造函数
• 类定义中含有一个该类的静态私有对象
• 该类提供了一个静态的公有方法用于创建或获取它本身的静态私有对象

1.2单例模式实现方法(懒汉模式)

私有对象 单例大约有两种实现方法:懒汉 与 饿汉。
• 懒汉模式: 当第一次使用时才创建一个唯一的实例对象,从而实现延迟加载 的效果。
CSDN:https://blog.csdn.net/ZYZMZM_
懒汉单例模式(非线程安全版本)


//=======================懒汉单例模式(非线程安全版本)=========================
class CSingleton
{
public:

	static CSingleton * getSingleton()
	{
		//	msin为NULL表示类实例尚未初始化,则初始化类实例,否则,直接返回之前创建的类实例指针
		if(msin == NULL)	
		{
			msin = new CSingleton();
		}
		return msin;
	}

	// 定义内嵌类,专职处理类实例的销毁
	class CDestroy	
    {
    public:
        ~CDestroy()
        {
			if(CSingleton::msin != NULL)
			{
				delete CSingleton::msin;
				cout << "~CSingleton()" << endl;
			}   
        }
    };

    static CDestroy mDel;

private:
	static CSingleton * msin;
	
	// 构造函数私有化
	CSingleton() 
	{
		cout << "CSingleton()" << endl;
	}
};

// 懒汉模式初始化不定义类实例,直到需要使用时才调用公共接口创建
CSingleton* CSingleton :: msin = NULL;	
CSingleton::CDestroy mDel;

int main()
{
	//CSingleton s1;
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();	// 第一次调用,初始化类实例,并返回指向该类实例的指针
	CSingleton *s2 = CSingleton::getSingleton();	// 第二次调用,返回之前创建的类实例指针
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
}

懒汉单例模式(线程安全版本):普通互斥锁版本


//=======================懒汉单例模式(线程安全版本):普通互斥锁版本=========================
class CSingleton
{
public:
	static CSingleton * getSingleton()
	{
		//	加锁
		pthread_mutex_lock(&mutex);	
		cout << "lock()" << endl;

		if (msin == NULL)
		{
			msin = new CSingleton();
		}

		// 解锁
		pthread_mutex_unlock(&mutex);	
		cout << "unlock()" << endl;
		return msin;
	}

	class CDestroy
    {
    public:
        ~CDestroy()
        {
			if(CSingleton::msin != NULL)
			{
				delete CSingleton::msin;
				cout << "~CSingleton()" << endl;
			}   
        }
    };

    static CDestroy mDel;

private:
	CSingleton()
	{
		cout << "CSingleton()" << endl;
	}

	static CSingleton* msin;
	static pthread_mutex_t mutex;
};

CSingleton* CSingleton::msin = NULL;
pthread_mutex_t CSingleton::mutex = PTHREAD_MUTEX_INITIALIZER;	// 初始化互斥锁
CSingleton::CDestroy mDel;

int main()
{
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();
	CSingleton *s2 = CSingleton::getSingleton();
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
}

懒汉单例模式(线程安全版本优化):双重校验锁


//=======================懒汉单例模式(线程安全版本优化):双重校验锁=========================
class CSingleton
{
public:
	// 双重校验锁保证线程安全
	static CSingleton* getSingleton()
	{
		if (msin == NULL) 
		{
			pthread_mutex_lock(&mutex);
			cout << "lock()" << endl;
			
			// 注意线程安全单例模式的DCL问题
			if (msin == NULL)
			{
				msin = new CSingleton();
			}

			pthread_mutex_unlock(&mutex);
			cout << "unlock()" << endl;
		}
		return msin;
	}

	class CDestroy
    {
    public:
        ~CDestroy()
        {
			if(CSingleton::msin != NULL)
			{
				delete CSingleton::msin;
				cout << "~CSingleton()" << endl;
			}   
        }
    };

    static CDestroy mDel;

private:
	CSingleton()
	{
		cout << "CSingleton()" << endl;
	}

	static CSingleton* msin;
	static pthread_mutex_t mutex;
};

CSingleton* CSingleton::msin = NULL;
pthread_mutex_t CSingleton::mutex = PTHREAD_MUTEX_INITIALIZER;
CSingleton::CDestroy mDel;

int main()
{
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();
	CSingleton *s2 = CSingleton::getSingleton();
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
}

内部静态变量保证线程安全


// =================内部静态变量保证线程安全=============================
#include <iostream>
#include <pthread.h>
using namespace std;
class CSingleton
{
public:
	static CSingleton *getSingleton()
	{
		// 使用函数内部静态变量,在其初始化时gcc编译器会自动在其前后进行加锁解锁,保证多线程间互斥访问
		static CSingleton msin;			
		return &msin;
	}
    	~CSingleton()
	{
		cout << "~CSingleton()" << endl;
	}
	
private:
	CSingleton()
	{
		cout << "CSingleton()" << endl;
	}
	
	static pthread_mutex_t mutex;
};

pthread_mutex_t CSingleton::mutex = PTHREAD_MUTEX_INITIALIZER;

int main()
{
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();
	CSingleton *s2 = CSingleton::getSingleton();
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
}

1.3单例模式实现方法(饿汉模式)

• 饿汉模式: 程序启动时就创建一个唯一的实例对象,即单例类定义的时候就 进行实例化。 饿汉单例模式

  1. 构造函数私有化
    1. 类定义时便创建实例
    1. 私有的静态类指针指向类的实例(类外声明)
    1. 公有的静态方法去获取一个访问实例的访问点
    1. 定义一个静态的嵌套类对象的析构函数去析构单例对象,待程序结束销毁类 实例

//=======================饿汉单例模式=========================
class CSingleton
{
public:
	// 静态公共接口,返回指向类实例的指针
	static CSingleton * getSingleton()	
	{
		return msin;
	}
	
	 // error ,主函数需显式delete指针,调用析构,析构函数中delete再次调用析构,循环递归。
	/*~CSingleton()  
	{
		delete msin;
		msin = NULL;
		cout << "~CSingleton()" << endl;
	}*/
	
	// 定义内嵌类,专职处理类实例的销毁
	class CDestroy	
    {
    public:
        ~CDestroy()
        {
			if(CSingleton::msin != NULL)
			{
				delete CSingleton::msin;
				msin = NULL;
				cout << "~CSingleton()" << endl;
			}   
        }
    };

	// 定义静态类对象,程序结束调用该类析构函数,析构全局唯一的类实例
    static CDestroy mDel;	

private:
	static CSingleton * msin;

	// 构造函数私有化
	CSingleton()	
	{
		cout << "CSingleton()" << endl;
	}
};

// 饿汉模式,在类定义时就初始化类实例
CSingleton* CSingleton :: msin = new CSingleton();	
CSingleton::CDestroy mDel;

int main()
{
	//CSingleton s1;
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();
	CSingleton *s2 = CSingleton::getSingleton();
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
	//delete s1;
}

2.单例模式使用场景

单例模式的适用场景 • 系统只需要一个实例对象,或者考虑到资源消耗的太大而只允许创建一个对象。 • 客户调用类的单个实例只允许使用一个公共访问点,除了该访问点之外不允许 通过其它方式访问该实例(就是共有的静态方法)。

猜你喜欢

转载自blog.csdn.net/sunshinecandy/article/details/89281160
今日推荐