设计模式-单例模式

设计模式-单例模式

简单介绍

  • 单例模式是为某个类创建全局唯一的静态实例
  • 通过维护一个 static 的成员变量来记录这
    个唯一的对象实例。通过提供一个 staitc 的接口 instance 来获得这个唯一的实例。

类图

在这里插入图片描述

代码

懒汉模式:第一次用到类的实例的时候才回去实例化。
版本一:存在线程安全问题以及内存泄漏问题

class singleton   //实现单例模式的类  
  {  
  private:  
      private:
	  Singleton(){}//构造
	  Singleton(const Singleton &clone){} //拷⻉构造
	  Singleton& operator=(const Singleton&) {}
	  static Singleton * _instance;
  public:  
      static singleton* GetInstance()  
      {  
          if (Instance == NULL) //判断是否第一调用  
              Instance = new singleton();  
          return Instance;  
      }  
  }; 
  Singleton* Singleton::_instance = nullptr;//静态成员需要初始化

版本二:存在线程安全问题无内存泄漏问题

 class Singleton {
 public:
  	static Singleton * GetInstance() {
  		if (_instance == nullptr) {
  			_instance = new Singleton();
  			atexit(Destructor);	//程序退出时调用Destructor函数
 		 }
 		 return _instance;
  }
  ~Singleton() {}
 private:
	  static void Destructor() {
  		if (nullptr != _instance) {
  			delete _instance;
  			_instance = nullptr;
  		}
  }
  Singleton();//构造
  Singleton(const Singleton &cpy); //拷⻉构造
  Singleton& operator=(const Singleton&) {}
  static Singleton * _instance;
 }
 Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
// 还可以使⽤ 内部类,智能指针来解决; 此时还有线程安全问题

版本三:无线程安全问题无内存泄漏问题,但存在指令重排序问题

#include <mutex>
class Singleton { // 懒汉模式 lazy load
	public:
		 static Singleton * GetInstance() {
			 //std::lock_guard<std::mutex> lock(_mutex); // 3.1 切换线程
			 if (_instance == nullptr) {
				 std::lock_guard<std::mutex> lock(_mutex); // 3.2
				 if (_instance == nullptr) {
					 _instance = new Singleton();	//指令重排序
					 atexit(Destructor);
				 }
			 }
			 return _instance;
 		}
private:
		 static void Destructor() {
			 if (nullptr != _instance) {
				 delete _instance;
				 _instance = nullptr;
			 }
		 }
		 Singleton(){} //构造
		 Singleton(const Singleton &cpy){} //拷⻉构造
		 Singleton& operator=(const Singleton&) {}
		 static Singleton * _instance;
		 static std::mutex _mutex;
}
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化

版本四:无线程安全问题无内存泄漏问题,无指令重排序问题

#include <mutex>
#include <atomic>
class Singleton {
public:
	 static Singleton * GetInstance() {
		 Singleton* tmp = _instance.load(std::memory_order_relaxed);
		 std::atomic_thread_fence(std::memory_order_acquire);//获取内存屏障
		 if (tmp == nullptr) {
			 std::lock_guard<std::mutex> lock(_mutex);
			 tmp = _instance.load(std::memory_order_relaxed);
			 if (tmp == nullptr) {
				 tmp = new Singleton;
				 std::atomic_thread_fence(std::memory_order_release);//释放内存屏障
				 _instance.store(tmp, std::memory_order_relaxed);
				 atexit(Destructor);
			 }
		 }
		 return tmp;
	 }
	 
private:
	 static void Destructor() {
	 	Singleton* tmp = _instance.load(std::memory_order_relaxed);
	 	if (nullptr != tmp) {
			 delete tmp;
		 }
 	 }
	 Singleton(){}
	 Singleton(const Singleton&) {}
	 Singleton& operator=(const Singleton&) {}
	 static std::atomic<Singleton*> _instance;
	 static std::mutex _mutex;
};
std::atomic<Singleton*> Singleton::_instance;//静态成员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化
// g++ Singleton.cpp -o singleton -std=c++11

版本五:解决版本四的代码繁琐问题,但将对象创建到了全局区,全局区空间有限

// c++11 magic static 特性:如果当变量在初始化的时候,并发同时进⼊声明语句,并发
线程将会阻塞等待初始化结束。
class Singleton
{
public:
	 ~Singleton(){}
	 static Singleton& GetInstance() {
		 static Singleton instance;
		 return instance;
	 }
private:
	 Singleton(){}
 	 Singleton(const Singleton&) {}
	 Singleton& operator=(const Singleton&) {}
};
// 继承 Singleton
// g++ Singleton.cpp -o singleton -std=c++11
/*该版本具备 版本5 所有优点:
1. 利⽤静态局部变量特性,延迟加载;
2. 利⽤静态局部变量特性,系统⾃动回收内存,⾃动调⽤析构函数;
3. 静态局部变量初始化时,没有 new 操作带来的cpu指令reorder操作;
4. c++11 静态局部变量初始化时,具备线程安全;
*/

版本六:支持模板的单例模式

template<typename T>
class Singleton {
public:
 	static T& GetInstance() {
 		 static T instance; // 这⾥要初始化DesignPattern,需要调⽤
						    //DesignPattern 构造函数,同时会调⽤⽗类的构造函数。
		 return instance;
	 }
protected:
	 virtual ~Singleton() {}
	 Singleton() {} // protected修饰构造函数,才能让别⼈继承
	 Singleton(const Singleton&) {}
	 Singleton& operator =(const Singleton&) {}
};
class DesignPattern : public Singleton<DesignPattern> {
 	 friend class Singleton<DesignPattern>; // friend 能让 Singleton<T> 访
										    //问到 DesignPattern构造函数
private:
	 DesignPattern(){}
	 DesignPattern(const DesignPattern&) {}
	 DesignPattern& operator=(const DesignPattern&) {}
}

饿汉模式:程序开始运行时就加载完成

  class singleton   //实现单例模式的类  
  {  
   private:  
      singleton() {}  //私有的构造函数  
      singleton(const singleton&) {}
	  singleton& operator =(const singleton&) {}
	  static singleton *Instance = new singleton ;
   public:  
      static singleton* GetInstance()  
      {  
          return &Instance;  
      }  
  }; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

长不大的程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值