C++/python之设计模式(1)之什么是单例模式

C++/python之设计模式(1)之什么是单例模式

注:整理一些突然学到的C++、python知识,随时mark一下
例如:忘记的关键字用法,新关键字,新数据结构


设计模式整理

  • C++/python之设计模式(1)之什么是单例模式
  • 一、 单例模式
    • 1、C++单例模式例子
    • 2、python单例模式例子
  • 总结


提示:本文为 C++、python 中单例模式的写法和举例


一、 单例模式

  单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类仅有一个实例,并提供一个全局性的访问点来获取该实例。单例模式在多种场景中都很有用,例如配置信息的读取、日志记录、线程池管理、数据库连接池等,这些场景通常只需要一个全局唯一的对象来执行特定的任务。

要实现单例模式,通常需要遵循以下步骤:

将构造函数私有化:通过将构造函数设为私有,可以阻止类的外部代码通过new关键字创建该类的实例。

在类内部创建静态实例:由于构造函数是私有的,类的外部无法创建实例,因此需要在类内部创建一个静态的实例。这个实例会在类首次被加载到内存时创建。

提供公共的静态方法获取实例:为了从类的外部获取这个唯一的实例,需要提供一个公共的静态方法,如getInstance(),用于返回这个静态实例。

禁止拷贝:为了防止通过拷贝构造函数和拷贝赋值操作符创建额外的实例,通常将它们设为私有或者禁用(使用= delete)。

1、C++单例模式例子

下面是一个简单的单例模式的C++实现示例:

cpp

#include <iostream>  
#include <memory>  class Singleton {  
private:  // 私有构造函数,防止外部创建实例  Singleton() {  std::cout << "Singleton instance created." << std::endl;  }  // 禁用拷贝构造函数  Singleton(const Singleton&) = delete;  // 禁用拷贝赋值操作符  Singleton& operator=(const Singleton&) = delete;  // 静态成员变量,保存唯一实例  static std::unique_ptr<Singleton> instance;  public:  // 静态方法,返回唯一实例  static Singleton* getInstance() {  if (!instance) {  instance.reset(new Singleton());  }  return instance.get();  }  // 其他成员函数...  void doSomething() {  std::cout << "Singleton doing something." << std::endl;  }  
};  // 类外初始化静态成员变量  
std::unique_ptr<Singleton> Singleton::instance = nullptr;  int main() {  Singleton* singleton1 = Singleton::getInstance();  Singleton* singleton2 = Singleton::getInstance();  // 检查是否指向同一个实例  if (singleton1 == singleton2) {  std::cout << "singleton1 and singleton2 are the same instance." << std::endl;  }  singleton1->doSomething();  return 0;  
}

在这个例子中,Singleton类通过以下方式确保单例行为:

构造函数是私有的,因此外部代码无法创建Singleton的实例。
静态成员变量instance是一个std::unique_ptr,它负责在程序结束时自动删除Singleton的唯一实例
getInstance()方法检查instance是否为空,如果是,则创建一个新的Singleton实例并返回其指针。由于instance是静态的,它只会被初始化一次,从而确保只有一个实例被创建。
拷贝构造函数和拷贝赋值操作符被禁用,防止了额外的实例被创建。
这个实现也考虑到了线程安全,因为在多线程环境下,可能会有多个线程同时调用getInstance()方法,从而导致创建多个实例。为了确保线程安全,通常需要使用互斥锁或其他同步机制来保护对instance的访问。在上面的示例中,由于使用了std::unique_ptr,在C++11及以后的版本中,其初始化是线程安全的,但getInstance()方法中的条件判断(如果实例为空则创建)并不是线程安全的,实际使用时需要添加适当的同步机制。

2、python单例模式例子

在Python中实现单例模式通常不需要像C++那样显式地控制构造函数和拷贝操作。Python提供了更简洁的方法来实现这一模式。下面是一个简单的Python单例模式的实现:

python

class Singleton:  _instance = None  def __new__(cls):  if not cls._instance:  cls._instance = super(Singleton, cls).__new__(cls)  return cls._instance  def do_something(self):  print("Singleton is doing something.")  # 使用单例  
singleton1 = Singleton()  
singleton2 = Singleton()  # 检查是否指向同一个实例  
if singleton1 is singleton2:  print("singleton1 and singleton2 are the same instance.")  singleton1.do_something()

在Python中,我们使用__new__方法而不是__init__方法来控制实例的创建。__new__方法在__init__之前被调用,用于创建并返回实例对象。在上面的代码中,_instance是一个类变量,它保存了单例的唯一实例。在__new__方法中,我们检查_instance是否为None,如果是,则调用父类的__new__方法创建一个新的实例并将其赋值给_instance。随后,我们总是返回_instance,确保无论多少次调用Singleton(),都返回同一个实例。

请注意,Python的单例实现不需要显式地禁止拷贝,因为Python中的对象是通过引用传递的,而不是通过值传递。因此,赋值操作实际上只是复制引用,而不是复制对象本身。此外,Python也没有像C++那样的拷贝构造函数和拷贝赋值操作符需要特别处理。

另外,如果你需要线程安全的单例,Python的__new__方法通常也已经是线程安全的,因为在CPython解释器中,全局解释器锁(GIL)确保了同一时间只有一个线程可以执行Python字节码。然而,如果你使用的是多进程环境或者对性能有严格要求的场景,可能需要使用更复杂的线程同步机制。在大多数情况下,简单的单例实现就已经足够了。

在Python中,super()函数用于调用父类(超类)的一个方法。当子类需要重写父类的方法,但又想保留父类的一些功能时,可以使用super()来调用父类的方法。在单例模式的上下文中,使用super()是为了确保当我们创建单例类的实例时,仍然按照正常的对象创建流程调用父类(即object类,因为所有Python类最终都继承自object)的__new__方法。

super(Singleton, cls).new(cls)做了以下几件事情:

super(Singleton, cls)返回一个临时对象,这个对象绑定到Singleton类的父类(在这种情况下是object类),并接收Singleton类作为第一个参数和当前类(由cls变量表示)作为第二个参数。

.new(cls)调用object类的__new__方法,并传入当前类(cls)作为参数。这实际上是请求Python为cls类创建一个新的实例。

在单例模式中,使用super()的目的是确保Singleton类的新实例是通过正常的Python对象创建机制来创建的,然后再通过我们的单例逻辑(即检查_instance是否为None)来确保我们不会意外地创建多个实例。

总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3746.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java(IO异常解释(为什么要捕获异常,为什么要给NULL)

实现copy的代码&#xff1a; package a0420.iotest1.Test2;import java.io.IOException;public class Test {public static void main(String[] args) {CopyMethod.FileCopy("D:\\idealTestio\\copy.txt","D:\\idealTestio\\finalPase");} }主要想解释一下…

Unity类银河恶魔城学习记录15-1,2 p153 Audio Manager p154 Audio distance limiter

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili AudioManager.cs using System.Collections; using System.Collections.Gen…

三大语音机器人:如何提升销售效率

如今&#xff0c;在互联网技术的支持下&#xff0c;越来越多的企业开始采用电销方式来推销他们的产品或服务。当然&#xff0c;电销的效率往往取决于销售过程中是否采用了高效的工具和方式。不过&#xff0c;对于一些销售人员而言&#xff0c;保持高效率从来不是一件容易的事情…

Ubuntu下载的nginx的位置

位置在/etc/nginx 启动nginx systemctl status nginx上面的命令不合适&#xff0c;就重启nginx sudo service nginx restart 关闭nginx nginx -s stop Ubuntu默认的html地址在该文件夹中的default中&#xff1a; /etc/nginx/sites-available if ($http_host ~* "^(w…

【计算机系统基础读书笔记】1.1.2 冯诺依曼机基本结构

1.1.2 冯诺依曼机基本结构 冯诺依曼机基本结构如图所示&#xff1a; 模型机中主要包括&#xff1a; 主存储器&#xff1a;用来存放指令和数据&#xff0c;简称主存或内存&#xff1b; 算数逻辑部件&#xff08;Arithmetic Logic Unit&#xff0c;简称ALU&#xff09;&#x…

实现SpringMVC底层机制(二)

文章目录 1. 动态获取spring配置文件1.修改SunWebApplicationContext.java2.修改SunDispatcherServlet.java 2.自定义Service注解1.需求分析2.编写Monster.java3.自定义Service注解4.编写Service接口MonsterService.java5.编写Service实现类MonsterServiceImpl.java6.修改SunWe…

华火电燃灶:市场认可度最高的品牌

华火电燃灶市场认可度高&#xff0c;这得益于其独特的技术优势、卓越的产品性能以及广泛的市场应用。作为一种新型的燃气灶具&#xff0c;华火电燃灶在市场上的表现备受瞩目&#xff0c;成为了众多消费者和业内人士关注的焦点。 首先&#xff0c;华火电燃灶的技术优势是其市场认…

pytorch-激活函数与GPU加速

目录 1. sigmod和tanh2. relu3. Leaky Relu4. selu5. softplus6. GPU加速7. 使用GPU加速手写数据训练 1. sigmod和tanh sigmod梯度区间是0&#xff5e;1&#xff0c;当梯度趋近0或者1时会出现梯度弥散的问题。 tanh区间时-1&#xff5e;1&#xff0c;是sigmod经过平移和缩放而…

【毕设绝技】基于 SpringCloud 的在线交易平台商城的设计与实现-数据库设计(三)

毕业设计是每个大学生的困扰&#xff0c;让毕设绝技带你走出低谷迎来希望&#xff01; 基于 SpringCloud 的在线交易平台商城的设计与实现 一、数据库设计原则 在系统中&#xff0c;数据库用来保存数据。数据库设计是整个系统的根基和起点&#xff0c;也是系统开发的重要环节…

Matlab|交直流混合配电网潮流计算(统一求解法)

目录 1 主要内容 算例模型 统一求解法迭代方程 算法流程图 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序为matlab代码&#xff0c;采用统一求解法对交直流混合配电网进行潮流计算&#xff0c;统一迭代法又称统一求解法&#xff0c;其思路是将混联系统中的交流网…

强化学习的智能体概念与代码实例

在强化学习中&#xff0c;智能体&#xff08;agent&#xff09;是与环境进行交互并学习如何做出决策以达到某种目标的实体。智能体通常具有以下几个组成部分&#xff1a; 策略&#xff08;Policy&#xff09;&#xff1a;智能体的策略定义了在给定状态下选择动作的规则或概率分…

C语言 | Leetcode C语言题解之第44题通配符匹配

题目&#xff1a; 题解&#xff1a; bool allStars(char* str, int left, int right) {for (int i left; i < right; i) {if (str[i] ! *) {return false;}}return true; } bool charMatch(char u, char v) { return u v || v ?; };bool isMatch(char* s, char* p) {in…

React Hooks(常用)笔记

一、useState&#xff08;保存组件状态&#xff09; 1、基本使用 import { useState } from react;function Example() {const [initialState, setInitialState] useState(default); } useState(保存组件状态) &#xff1a;React hooks是function组件(无状态组件) &#xf…

探索 Chrome 插件开发之旅

浏览器扩展程序拥有无限可能性&#xff0c;它们能丰富我们的浏览体验&#xff0c;提升工作效率&#xff0c;甚至改变网络世界的交互方式。谷歌 Chrome 浏览器的插件生态尤为繁荣&#xff0c;本文将引导你走进 Chrome 插件开发的世界&#xff0c;从入门基础知识到实战案例&#…

IDEA生成测试类

方法一 具体流程: 选中要生成的测试类------------>选择code选项------------>选择Generate选项---------->选择test选项---------->选择要生成的方法 第一步: 光标选中需要生成测试类的类 找到code选项 选中Generate选项 选中test选项 选中你要生成的测试…

【嵌入式笔试题】C语言笔试题(4)

C语言非常之经典的笔试题。 4.综合题(18道) 4.1下面代码输出是几? int main() { int j = 2; int i = 1; if(i = 1) j = 3; if(i = 2) j = 5; printf("%d", j); } 答案: 输出为 5 。 解读: 注意 if 的条…

授人以渔 选购篇十二:路由器选购要点

文章目录 系列文章Wi-Fi 标准&#xff1a;WiFi6或以上无线速度&#xff1a;千兆以上Mesh组网有线端口LAN端口数量&#xff1a;布线拓扑结构决定LAN端口速率&#xff1a;千兆WLAN端口&#xff1a;2.5G其他&#xff1a;Link Aggregation&#xff08;链路聚合&#xff09; 附加接口…

简单的jmeter上传文件脚本

1、设置上传接口的headers的值 2、添加post请求

数据结构系列-二叉树之前序遍历

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 这篇文章&#xff0c;我们主要的内容是对二叉树当中的前历的算法进行讲解&#xff0c;二叉树中的算法所要求实现的是 从根到左子树再到右子树的遍历顺序&#xff0c;可能这样不太…

什么是用户体验(UX)文案,为什么它很重要?

网上购物如今比以往任何时候都更加相关。所以我们将以此为例说明什么是用户体验&#xff08;UX&#xff09;文案&#xff0c;以及为什么它很重要。 假设你去了一个在线商店。你需要执行一系列操作&#xff1a; 找到合适的部分选择你感兴趣的产品弄清楚它们是什么&#xff0c;…