设计模式学习笔记(单例模式)

一、单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式是对全局变量的一种改进。全局变量空间利用率比较低,且在项目中是一个不安全隐患,特别是在多线程程序中,会有很多的不可预测性;同时,使用全局变量,也不符合面向对象的封装原则。

二、实例

1、基础版本:

#include <iostream>
using namespace std;

class Singleton
{
public:
	static Singleton *GetInstance()
	{
		if (m_Instance == NULL )
		{
			m_Instance = new Singleton ();
		}
		return m_Instance;
	}

	static void DestoryInstance()
	{
		if (m_Instance != NULL )
		{
			delete m_Instance;
			m_Instance = NULL ;
		}
	}

	int GetTest()//该函数用于测试
	{
	     return m_Test;
	}

private:
	Singleton(){ m_Test = 10; }
	static Singleton *m_Instance;//一个静态成员变量,程序结束时,系统会自动调用它的析构函数
	int m_Test;
};

Singleton *Singleton ::m_Instance = NULL;

int main(int argc , char *argv [])
{
	Singleton *singletonObj = Singleton ::GetInstance();
	cout<<singletonObj->GetTest()<<endl;

	Singleton ::DestoryInstance();
	return 0;
}
但该版本没有考虑多线程情况。当我们运行在多线程环境的时候,静态变量的初始化来实现单件,是不可靠的――直接的说,静态变量有可能初始化多次!
2、改进版1(对版本1进行了改进,但仍然没解决多线程问题)

#include <iostream>
using namespace std;

class Singleton
{
public:
	static Singleton *GetInstance()
	{
		static Singleton m_Instance;//局部静态变量,非常强大的方法,完全实现了单例的特性,而且代码量更少,也不用担心单例销毁的问题。
		return &m_Instance;//返回的是一个指针,避免了问题
	}

	int GetTest()
	{
		return m_Test++;
	}

private:
	Singleton(){ m_Test = 10; };
	int m_Test;
};

int main(int argc , char *argv [])
{
	Singleton *singletonObj = Singleton ::GetInstance();
	cout<<singletonObj->GetTest()<<endl;

	singletonObj = Singleton ::GetInstance();
	cout<<singletonObj->GetTest()<<endl;
}

GetInstance函数如果返回引用,则Singleton singleton = Singleton :: GetInstance();这么做就出现了一个类拷贝的问题,这就违背了单例的特性。产生这个问题原因在于:编译器会为类生成一个默认的构造函数,来支持类的拷贝。


3、考虑线程安全

class Lock  
{  
private:         
    CCriticalSection m_cs;  
public:  
    Lock(CCriticalSection  cs) : m_cs(cs)  
    {  
        m_cs.Lock();  
    }  
    ~Lock()  
    {  
        m_cs.Unlock();  
    }  
};  
  
class Singleton  
{  
private:  
    Singleton();  
    Singleton(const Singleton &);  
    Singleton& operator = (const Singleton &);  
  
public:  
    static Singleton *Instantialize();  
    static Singleton *pInstance;  
    static CCriticalSection cs;  
};  
  
Singleton* Singleton::pInstance = 0;  
  
Singleton* Singleton::Instantialize()  
{  
    if(pInstance == NULL)  
    {   //double check  
        Lock lock(cs);           //用lock实现线程安全,用资源管理类,实现异常安全  
        //使用资源管理类,在抛出异常的时候,资源管理类对象会被析构,析构总是发生的无论是因为异常抛出还是语句块结束。  
        if(pInstance == NULL)  
        {  
            pInstance = new Singleton();  
        }  
    }  
    return pInstance;  
}  



猜你喜欢

转载自blog.csdn.net/sinat_22991367/article/details/77938883