首页 > 其他分享 >单例模式

单例模式

时间:2022-09-20 22:23:55浏览次数:77  
标签:mtx 静态 SingletonLazy 模式 instance 实例 单例

理论

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式的好处:

单例模式因为 Singleton 类封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它,简单地来说就是对唯一实例地受控访问。

单例模式实现方法:

  1. 声明自己的静态私有对象

  2. 将创造对象的构造函数设置为私有,那么外界就无法创建对象了

  3. 提供公有的访问对象的静态函数

预备知识:静态成员和静态变量:

  1. 将成员或函数声明为静态的,那么这些成员和变量在类的所有对象之间是共享的,相当于类内全局变量。其中一个用途用来记录该类实例了多少对象。
  2. 静态成员函数是没有this指针的,C++中调用方式 <类名>::<成员>
  3. 一般类在实例化对象的时候会为类成员分配内存空间。但是静态成员函数和静态成员变量在实例化对象的时候不会被分配内存空间,因为在对象创建之前(编译阶段)就已经被分配了内存。
  4. 静态成员变量不能在类内初始化,这样可以防止每个对象都包含静态成员。

预备知识:互斥锁

  1. 头文件#include《mutex》

  2. 实例化:std::mutex mtx

  3. 上锁:mtx.lock(), mtx.try_lock(); 解锁mtx.unlock()

实例

单线程单例模式

#include <iostream>
using namespace std;

//单例模式--懒汉式
class SingletonLazy {
private:
	SingletonLazy(){}
	static SingletonLazy* instance;  //静态成员变量应在类外初始化,且不能带static关键字

public:
	static SingletonLazy* GetInstance() {    //提供单例的访问接口
		if (instance == nullptr) {      //第一次调用时,分配内存空间
			instance = new SingletonLazy();
		}
		return instance;
	}
};
SingletonLazy* SingletonLazy::instance = nullptr;  //在类外初始化静态成员变量

//单例模式--饿汉式
class SingletonHungry {
private:
	SingletonHungry() {}
	static SingletonHungry* instance;

public:
	static SingletonHungry* GetInstance() {
		return instance;
	}
};
//在主函数之前就实例化了
SingletonHungry* SingletonHungry::instance = new SingletonHungry();

int main()
{
	SingletonLazy* s1 = SingletonLazy::GetInstance();
	SingletonLazy* s2 = SingletonLazy::GetInstance();
	if (s1 == s2){
		cout << "s1与s2为同一实例" << endl;
	}
	SingletonHungry* s3 = SingletonHungry::GetInstance();
	SingletonHungry* s4 = SingletonHungry::GetInstance();
	if (s3 == s4){
		cout << "s3与s4为同一实例" << endl;
	}

	system("pause");
	return 0;
}

饿汉式单例类:这种静态初始化的方式是在自己被加载时就将自己实例化

懒汉式单例类:是在第一次被引用时,才会将自己实例化

区别:饿汉式单例模式是类一加载就实例化的对象,要提前占用系统资源。而懒汉式,面临多线程访问的安全性问题,需要做双重锁定这样的处理才可以保证安全。

多线程单例模式

上述单线程单例模式在多个线程同时检测到 instance == nullptr 时,会创建多个 Singleton ;所以需要进行上锁

public:
	static Singleton* GetInstance() {  //提供单例的访问接口
		mtx.lock();
		if (instance == nullptr) {         //第一次调用时,分配内存空间
			instance = new Singleton();
		}
		mtx.unlock();
		return instance;
	}

这里每次运行 GetInstance 的时候都要进行互斥锁的操作,影响效率。所以人们发明了双锁

public:
	static Singleton* GetInstance() {  //提供单例的访问接口
		if (instance == nullptr){
			mtx.lock();
			if (instance == nullptr) {         //第一次调用时,分配内存空间
				instance = new Singleton();
			}
			mtx.unlock();
		}
		return instance;
	}

 

参考博客: Coder-Goo的博客-CSDN博客_c++单例设计模式

 

标签:mtx,静态,SingletonLazy,模式,instance,实例,单例
From: https://www.cnblogs.com/kyzh-lhl/p/16712746.html

相关文章

  • Java单例模式
    单例模式  单例模式核心是保证一个类只有一个实例,并且提供一个访问实例的全局访问点。使用场景  需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过......
  • CSDN(markdown模式下)如何调整图片大小以及如何调整位置
    版权声明:本文为CSDN博主「圣喵」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/m0_66769266/article/details/1240......
  • 设计模式 -- Decorator(装饰模式)
    装饰模式(Decorator)在某些情况下,我们可能会“过度的使用继承来扩展对象的功能”,由于继承为类型引入静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的在......
  • java流之装饰者模式
    扩展类在于继承FilterInputStream,从而增强read和writer方法的能力输出流同样如此。   推荐文章:https://blog.csdn.net/hustzw07/article/details/80795855......
  • 【设计模式】之桥接模式
    桥接模式(BridgePattern)定义:将抽象化与实现化分离,使得双方可以独立变化。当然好多人看到这定义头都大了,什么叫抽象化?什么又叫实现化?还是举个例子吧。假如说,有个图形(G......
  • 我的设计模式之旅、14 模板方法模式
    编程旅途是漫长遥远的,在不同时刻有不同的感悟,本文会一直更新下去。思考总结思考问题多个类中包含许多相似代码,只是小部分代码不同。思考如何在保持算法结构完整的情况......
  • JS使用策略模式优化条件选择结构
    这段代码是采用if-else的方式判断多个不同的条件。functionpermission(role){if(role==="operations"){getOperationPermission()}elseif(role=......
  • 聊聊如何利用管道模式来进行业务编排(下篇)
    前言上篇文章我们介绍利用管道模式来进行业务编排的2种实现方式。本文又来介绍其他实现方式实现方式方式一:利用springboot自动装配1、新建管道实体@Data@AllArgsCo......
  • 【设计模式】Java设计模式 - 模板模式
    Java设计模式-模板模式......
  • 设计模式在业务系统中的应用
      本文的重点在于说明工作中所使用的设计模式,为了能够更好的理解设计模式,首先简单介绍一下业务场景。使用设计模式,可以简化代码、提高扩展性、可维护性和复用性。有哪......