设计模式(二):单例模式、工厂模式、抽象工厂、责任链、装饰器

本文详细介绍了设计模式中的单例模式、工厂模式、抽象工厂、责任链模式和装饰器模式,包括它们的定义、使用场景、实现细节及代码实现。通过实例讲解了每种模式的应用,如单例模式在多线程环境中的实现,工厂模式在创建复杂对象时的作用,以及装饰器模式如何动态地为对象添加职责。
摘要由CSDN通过智能技术生成

1. 单例模式

1.1 定义

  保证一个类仅有一个实例,并提供一个该实例的全局访问点。
  稳定点:一个人只有一个实例,并且提供一个全局访问点。
  变化点:可能存在多个不同类的单例。

1.2 使用场景

  

1.3 实现细节

//实现:
//1.静态成员确保一个类仅有一个实例,静态方法提供一个全局的访问点。
//2.构造函数和析构函数都声明为私有属性,确保全局唯一的单例不能调用构造方法创建,不能调用析构方法销毁。
//版本一:
//1. 并发下线程不安全, mutex加锁,懒汉模式----双重检测
//2. _instance是一个静态成员指针变量,new一个对象赋值给_instance,程序结束,堆上申请的内存没有被释放
		//1.智能指针 2.int atexit(void (*func)(void))
class Singleton {
   
public:
	static Singleton * GetInstance(){
   
		//std::lock_guard<std::mutex> lock(_mutex);
		//锁的粒度可以降低,只在_instance第一次创建的时候需要加锁
		if(_instance == nullptr){
   	
			std::lock_guard<std::mutex> lock(_mutex);
			if(_instance == nullptr)	//双重检测
				_instance = new Singleton();
			// int atexit(void (*func)(void)) 当程序正常终止时,调用指定的函数 func。
			//您可以在任何地方注册你的终止函数,但它会在程序终止的时候被调用。
			atexit(Destructor);
		}
		return _instance;
	}
private:
	static void Destructor(){
   
		if(nullptr != _instance){
   
			delete _instance;
			_instance = nullptr;
		}
	}
	Singleton(){
   }; //构造函数
	~Singleton(){
   }; //析构函数
	Singleton(const Singleton &) = delete; //拷贝构造函数
	Singleton& operator=(const Singleton&) = delete; //拷贝赋值构造函数
	Singleton(Singleton &&) = delete;
	Singleton& operator=(Singleton &&) = delete; //移动拷贝构造函数
	
	static Singleton *_instance;
	static std::mutex _mutex;
};
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
Singleton* Singleton::_mutex;//互斥锁初始化

  上一个版本,虽然解决了线程安全问题,和堆上内存释放,但是,在多核CPU环境下会对指令的执行顺序进行优化,指令重排。

#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) {
    
	          	/*
					operatoa new {}
					1.分配内存
					2.调用构造函数
					3.返回指令
					//多线程环境下 CPU 的热order操作 指令重排 1-》3-》2
				*/                
		        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(){
   
		if(nullptr != _instance){
   
			delete _instance;
			_instance = nullptr;
		}
	}
	Singleton(){
   }; //构造函数
	~Singleton(){
   }; //析构函数
	Singleton(const Singleton &) = delete; //拷贝构造函数
	Singleton& operator=(const Singleton&) = delete; //拷贝赋值构造函数
	Singleton(Singleton &&) = delete;
	Singleton& operator=(Singleton &&) = delete; //移动拷贝构造函数
	
	static Singleton *_instance;
	static std::mutex _mutex;
};
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
Singleton* Singleton::_mutex;//互斥锁初始化
// g++ Singleton.cpp -o singleton -std=c++11

  上面的代码使用了原语操作和内存屏障,代码实现比较复杂,利用 c++11 magic static 特性:如果当变量在初始化的时候,并发同时进⼊声明语句,并发线程将会阻塞等待初始化结束,代码实现较于容易些。

//利用C++11 magic static特性,解决了上面的所有问题
/*
	1. 利用静态局部变量延时加载的特性
	2. 利用局部变量特性,进程结束系统自动回收内存,自动调用析构函数
	3. 静态局部变量初始化是,没有new 操作带来的 CPU指令reorder操作
	4. C++11 静态局部变量初始化时,具备线程安全
*/
class Singleton{
   
public: 
	static Singleton& GetInstance(){
   
		static Singleton instance;
		return instance;
}
private:
	Singleton(){
   }; //构造函数
	~Singleton(){
   }; //析构函数
	Singleton(const Singleton &) = delete; //拷贝构造函数
	Singleton& operator=(const Singleton&) = delete; //拷贝赋值构造函数
	Singleton(Singleton &&) = delete;
	Singleton& operator=(Singleton &&) = delete; //移动拷贝构造函数
	
};

  考虑到可能存在多个不同类的单例,使用模板编程进行拓展

template<template T>
class Singleton{
   
public: 
	static T& GetInstance(){
   
		//这里要初始化DesingPattern ,需要调用DesingPattern 构造函数,同时会调用父类的构造函数。
		static T instance;
		return instance;
}
protected:	//DesingPattern 子类需要调用基类class Singleton<DesingPattern>的构造函数与析构函数
	Singleton(){
   }; //构造函数
	~Singleton(){
   }; //析构函数
private:
	Singleton(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值