当前位置: 首页 > news >正文

自学设计模式(类图、设计原则、单例模式 - 饿汉/懒汉)

设计模式需要用到面向对象的三大特性——封装、继承、多态(同名函数具有不同的状态)

UML类图 eg.—— 描述类之间的关系(设计程序之间画类图)

 +: public; #: protected; -: private; 下划线: static

属性名:类型(=默认值)

方法和变量分开-------

虚函数斜体,纯虚函数在虚函数类型后=0,并且类名斜体

类与类之间的关系:

1. 继承关系(空心三角形实线,箭头指父类)

2. 关联关系(单项关联、双向关联、自关联 - 链表)用带箭头和不带箭头的实现

3. 聚合关系(整体与部分的关系,整体析构部分不析构)空心菱形实线链接,指向整体

4. 组合关系(整体析构部分析构)实心菱形实线链接

5. 依赖关系(使用关系)带箭头的虚线,指向被依赖方

类之间的关系强弱:继承(泛化)>组合>聚合>关联>依赖(类图按类间最强关系就可)

设计模式三原则

单一职责原则(面向对象):

使得类的功能尽量单一,方便管理维护,避免类的臃肿。

开放封闭原则:

对于扩展是开放的,对于修改是封闭的,增加程序可维护性可扩展性。

依赖转换原则:

高层模块不应该依赖低层模块(应用程序不直接调用API),两个都应该依赖抽象。

抽象不依赖细节,细节应该依赖抽象。(里氏代换原则)

单例模式和任务队列(类的对象只能创建出一个)

一个项目中,全局范围内,某个类的实例有且仅有一个,通过这个实例向其他模块提供数据的全局访问。(简介访问实现对于变量的保护)

将类的默认构造函数和拷贝构造函数设为private,或者将两个函数=delete;

使类无法在外面创建对象,只能通过类名访问静态属性或者方法;

懒汉模式和饿汉模式

饿汉模式——定义类的时候创建单例对象(多线程下没有线程安全问题)

// 饿汉模式
#include <bits/stdc++.h>
using namespace std;class A{
public:A(const A& a) = delete;A& operator =(const A& a) = delete;static A* get(){return num;}print(){cout<<"单例模式的唯一实例";}
private:A() = default; // 默认构造 static A* num;
};A* A::num = new A;int main(){A* a = A::get();a->print(); return 0;
} 

懒汉模式——什么时候使用单例对象再去创建实例(多线程下存在线程安全问题)

// 懒汉模式
#include <bits/stdc++.h>
using namespace std;class A{
public:A(const A& a) = delete;A& operator =(const A& a) = delete;static A* get(){num = new A;return num;}print(){cout<<"单例模式的唯一实例";}
private:A() = default; // 默认构造 static A* num;
};A* A::num = nullptr;int main(){A* a = A::get();a->print(); return 0;
} 

懒汉模式的线程安全问题

可以通过双重检查锁定解决懒汉模式的线程安全问题:1. 互斥锁(导致效率低) 2. 实例创建判定

// 懒汉模式
#include <bits/stdc++.h> 
using namespace std;class A{
public:A(const A& a) = delete;A& operator =(const A& a) = delete;static A* get(){ // first checkif(num==nullptr){lk.lock();if(num==nullptr)num = new A; // second check lk.unlock();}return num;}print(){cout<<"单例模式的唯一实例";}
private:A() = default; // 默认构造 static A* num;static mutex lk;
};A* A::num = nullptr;
mutex A::lk;int main(){A* a = A::get();a->print(); return 0;
} 

通过原子变量(atomic - 底层控制机器指令执行顺序)解决双重检查锁定的问题;放置底层的机器指令不按理想顺序执行

// 懒汉模式
#include <bits/stdc++.h> 
using namespace std;class A{
public:A(const A& a) = delete;A& operator =(const A& a) = delete;static A* get(){ // first checkA* cur = task.load();if(cur==nullptr){lk.lock();cur = task.load();if(cur==nullptr){cur = new A; // second checktask.store(cur);} lk.unlock();}return cur;}print(){cout<<"单例模式的唯一实例";}
private:A() = default; // 默认构造 static A* num;static mutex lk;static atomic<A*> task;
};A* A::num = nullptr;
mutex A::lk;
atomic<A*> A::task;int main(){A* a = A::get();a->print(); return 0;
} 

使用静态局部对象解决线程安全问题

#include <bits/stdc++.h> 
using namespace std;class A{
public:A(const A& a) = delete;A& operator =(const A& a) = delete;static A* get(){ // first checkstatic A a;return &a; }print(){cout<<"单例模式的唯一实例";}
private:A() = default; // 默认构造 
};int main(){A* a = A::get();a->print(); return 0;
} 

并发执行应当等待变量完成初始化;

总结

1. 饿汉模式不存在线程安全问题

2. 懒汉模式通过双重检查锁定+原子变量或者静态局部对象(简单)可以解决线程安全问题       

实践(多线程模式下的任务模型)

#include <bits/stdc++.h>
using namespace std;// 饿汉模式
#include <bits/stdc++.h>
using namespace std;class A{
public:A(const A& a) = delete;A& operator =(const A& a) = delete;static A* get(){return num;}print(){cout<<"单例模式的唯一实例";}bool isempty(){lock_guard<mutex> locker(m_mutex);return mis.empty(); }void add_m(int node){lock_guard<mutex> locker(m_mutex);mis.push(node);}bool minus_m(){lock_guard<mutex> locker(m_mutex);if(mis.empty())return false;else{mis.pop();}return true;}int get_m(){lock_guard<mutex> locker(m_mutex);if(mis.empty())return -1;return mis.front();	}
private:A() = default; // 默认构造 static A* num;queue<int> mis;mutex m_mutex;
};A* A::num = new A;int main(){A *a = A::get();// 生产者thread t1([=](){for(int i = 0 ; i<10 ; i++){a->add_m(i+100);cout<<"push data: "<<i+100<<" "<<"threadId: "<<this_thread::get_id()<<endl;this_thread::sleep_for(chrono::milliseconds(500));} });// 消费者 thread t2([=](){this_thread::sleep_for(chrono::milliseconds(100));while(!a->isempty()){int cur = a->get_m();cout<<"take data: "<<cur<<" "<<"threadId: "<<this_thread::get_id()<<endl;a->minus_m();this_thread::sleep_for(chrono::milliseconds(1000));} });// 阻塞主线程 t1.join();t2.join();return 0;
} 

相关文章:

自学设计模式(类图、设计原则、单例模式 - 饿汉/懒汉)

设计模式需要用到面向对象的三大特性——封装、继承、多态&#xff08;同名函数具有不同的状态&#xff09; UML类图 eg.—— 描述类之间的关系&#xff08;设计程序之间画类图&#xff09; : public; #: protected; -: private; 下划线: static 属性名:类型&#xff08;默认值…...

python爬虫10:selenium库

python爬虫10&#xff1a;selenium库 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产…...

c++ java rgb与nv21互转

目录 jni函数 c++ rgb转nv21,可以转,不报错,但是转完只有黑白图 java yuv420保存图片,先转nv21,再保存ok: c++ yuv420月bgr互转,测试ok jni函数 JNIEXPORT void JNICALL Java_com_tencent_blazefacencnn_BlazeFaceNcnn_encode(JNIEnv *env,jobject thiz, jobject in…...

多视图聚类(multi-view clustering)简介

多视图聚类 目前大概有以下几种&#xff1a; 多视图k-means聚类多视图谱聚类多视图图聚类多视图子空间聚类 (multi-view subspace clustering)深度学习多视图聚类 (deep multi-view clustering) 其中多视图子空间聚类具有不错的数据表征能力。 对于多视图子空间聚类而言&…...

wazhu配置以及漏洞复现

目录 1.wazhu配置 进入官网下载 部署wazhu 修改网络适配器 重启 本地开启apache wazhu案例复现 前端页面 执行 1.wazhu配置 进入官网下载 Virtual Machine (OVA) - Installation alternatives (wazuh.com) 部署wazhu 修改网络适配器 重启 service network restart 本地…...

javaweb项目部署linux服务器遇到的问题

其他有关本次部署内容请参考本站其他文章 javaweb项目要用war包 IntelliJ IDEA 可以打包out里的子目录 D:\D盘文件\浏览器\webshop\out\artifacts\webshop_war_exploded>jar cvf webshop.war * 方法来源视频 18、web项目的打包与发布_哔哩哔哩_bilibili myeclipse项目…...

【数据结构OJ题】环形链表

原题链接&#xff1a;https://leetcode.cn/problems/linked-list-cycle/description/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 整体思路&#xff1a;定义快慢指针fast&#xff0c;slow&#xff0c;如果链表确实有环&#xff0c;fast指针一定会…...

PySpark-核心编程

2. PySpark——RDD编程入门 文章目录 2. PySpark——RDD编程入门2.1 程序执行入口SparkContext对象2.2 RDD的创建2.2.1 并行化创建2.2.2 获取RDD分区数2.2.3 读取文件创建 2.3 RDD算子2.4 常用Transformation算子2.4.1 map算子2.4.2 flatMap算子2.4.3 reduceByKey算子2.4.4 Wor…...

vue 在IOS移动端中 windon.open 等跳转外部链接后,返回不触发vue生命周期、mounted等相关事件-解决方法

做了一个列表的h5页面&#xff0c;通过点击列表跳转到外部链接&#xff0c;然后返回是回到原来页面状态&#xff0c;类似缓存。发现在ios端返回后&#xff0c;vue 的mounted() 、create()、路由监听等方法都不会执行。在安卓和pc 端都能正常调用。 解决方案&#xff1a;监听pa…...

股票预测和使用LSTM(长期-短期-记忆)的预测

一、说明 准确预测股市走势长期以来一直是投资者和交易员难以实现的目标。虽然多年来出现了无数的策略和模型&#xff0c;但有一种方法最近因其能够捕获历史数据中的复杂模式和依赖关系而获得了显着的关注&#xff1a;长短期记忆&#xff08;LSTM&#xff09;。利用深度学习的力…...

Docker搭建个人网盘、私有仓库

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘 [rootlocalhost ~]# docker pull mysql:5.6 [rootlocalhost ~]# docker pull owncloud [rootlocalhost ~]# docker run -itd --name mysql --env MYSQL_ROOT_PASSWORD123456 mysql:5.6 [rootlocalhost ~]# doc…...

3种获取OpenStreetMap数据的方法【OSM】

OpenStreetMap 是每个人都可以编辑的世界地图。 这意味着你可以纠正错误、添加新地点&#xff0c;甚至自己为地图做出贡献&#xff01; 这是一个社区驱动的项目&#xff0c;拥有数百万注册用户。 这是一个社区驱动的项目&#xff0c;旨在在开放许可下向每个人提供所有地理数据。…...

数据处理与统计分析——MySQL与SQL

这里写目录标题 1、初识数据库1.1、什么是数据库1.2、数据库分类1.3、相关概念1.4、MySQL及其安装1.5、基本命令 2、基本命令2.1、操作数据库2.2、数据库的列类型2.3、数据库的字段属性2.4 创建和删除数据库表2.5、数据库存储引擎2.6、修改数据库 3、MySQL数据管理3.1、外键 My…...

OpenCV之特征点匹配

特征点选取 特征点探测方法有goodFeaturesToTrack(),cornerHarris()和SURF()。一般使用goodFeaturesToTrack()就能获得很好的特征点。goodFeaturesToTrack()定义&#xff1a; void goodFeaturesToTrack( InputArray image, OutputArray corners,int maxCorners, double qualit…...

浅谈开关柜绝缘状态检测与故障诊断

贾丽丽 安科瑞电气股份有限公司 上海嘉定 201801 摘要:电力开关柜作为电力系统的关键设备广泛应用于输电配电网络&#xff0c;其运行可靠性直接影响着电力系统供电质量及安全性能。开关柜绝缘状态检测与故障诊断是及时维修、更换和预防绝缘故障的重要技术手段。在阐述开关柜绝…...

Mybatis 动态 SQL

动态 SQL 1. if 标签2. trim 标签3. where 标签4. set 标签5. foreach 标签 1. if 标签 if 标签有很多应用场景, 例如: 在用户进行注册是有些是必填项有些是选填项, 这就会导致前端传入的参数不固定如果还是将参数写死就很难处理, 这时就可以使用 if 标签进行判断 <insert …...

Android studio之 build.gradle配置

在使用Android studio创建项目会出现两个build.gradle&#xff1a; 一. Project项目级别的build.gradle &#xff08;1&#xff09;、buildscript{}闭包里是gradle脚本执行所需依赖&#xff0c;分别是对应的maven库和插件。 闭包下包含&#xff1a; 1、repositories闭包 2、d…...

【ElasticSearch】一键安装IK分词器无需其他操作

要注意的时下面命令中的es是我容器的名称&#xff0c;要换成你对应的es容器名 docker exec -it es /bin/bash # 进入容器 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis- ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.1…...

在Ubuntu上启动一个简单的用户登录接口服务

一个简单的用户登录接口 我使用 Python 和 Flask 框架来创建这个接口 首先&#xff0c;确保你已经安装了 Python 和 Flask。如果没有安装&#xff0c;可以通过以下命令在 Ubuntu 上安装&#xff1a; sudo apt update sudo apt install python3 python3-pip pip3 install Fla…...

【PHP】函数-作用域可变函数匿名函数闭包常用系统函数

文章目录 函数定义&使用命名规则参数种类默认值引用传递函数返回值return关键字 作用域global关键字静态变量 可变函数匿名函数闭包常用系统函数输出函数时间函数数学函数与函数相关函数 函数 函数&#xff1a;function&#xff0c;是一种语法结构&#xff0c;将实现某一个…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...