C++设计模式(更新中)
文章目录
- 1、创建型模式
- 1.1 简单工厂(Simple Factory)
- (1)示例
- (2)总结
- 1.2 工厂方法(Factory Method)
- (1)示例
- (2)总结
- 1.3 抽象工厂(Abstract Factory)
- (1)示例
- (2)总结
- 1.4 建造者(Builder)
- (1)示例
- (2)总结
1、创建型模式
1.1 简单工厂(Simple Factory)
简单工厂模式通过一个工厂类负责对象的创建,客户端只需提供参数,工厂类根据条件返回相应的对象。这种方式可以减少客户端对具体实现的依赖。
核心结构
- 工厂类:负责根据传入的参数生成具体对象。
- 产品抽象基类:定义所有产品的公共接口。
- 产品类:具体的实现类,继承自产品基类。
- 客户端:通过工厂类创建产品对象并调用其方法。
(1)示例
假设正在开发一个工具库,工具种类包含绘制工具 (DrawTool) 和擦除工具 (EraseTool)。为了简化工具对象的创建和使用,可以通过简单工厂模式来生成这些工具。
库代码实现
-
工具抽象类和具体工具类
Tool.h
:为了方便,这里没有分文件编写,实际中也可以分成Tool.h
+Tool.cpp
,工具太多也可以每个具体工具和工具接口类全部分开编写。之后的示例代码也是一样。#pragma once #include <iostream>// 工具基类 class Tool { public:virtual void UseTool() = 0; virtual ~Tool() = default; };// 具体工具类1 - 绘制工具 class DrawTool : public Tool { public:void UseTool() override{std::cout << "Using Draw Tool!" << std::endl;} };// 具体工具类2 - 擦除工具 class EraseTool : public Tool { public:void UseTool() override{std::cout << "Using Erase Tool!" << std::endl;} };
-
工厂类 (
ToolFactory.h
和ToolFactory.cpp
)
ToolFactory.h
:#pragma once #include <memory> #include "Tool.h"// 工厂类,用于创建工具对象 class ToolFactory { public:enum class ToolType{Draw,Erase};// 简单工厂创建工具的静态方法static std::unique_ptr<Tool> CreateTool(ToolType type); };
ToolFactory.cpp
:#include "ToolFactory.h"std::unique_ptr<Tool> ToolFactory::CreateTool(ToolType type) {switch (type){case ToolType::Draw:return std::make_unique<DrawTool>();case ToolType::Erase:return std::make_unique<EraseTool>();default:return nullptr;} }
使用者代码
使用者只需要引入 ToolFactory.h
,通过工厂类创建工具对象,而不需要知道具体的工具类 DrawTool
或 EraseTool
。这减少了客户端和库中具体实现的依赖关系。
从下面代码,可以看到,实际上使用者这边还是需要依赖于工具基类的信息的(没有包含Tool.h
是因为工厂类已经包含了),但是不需要知道具体的工具类的信息
Main.cpp
:
#include "ToolFactory.h" int main()
{// 使用工厂创建绘制工具std::unique_ptr<Tool> tool = ToolFactory::CreateTool(ToolFactory::ToolType::Draw);if (tool)tool->UseTool(); // 使用工厂创建擦除工具tool = ToolFactory::CreateTool(ToolFactory::ToolType::Erase);if (tool)tool->UseTool();return 0;
}
(2)总结
-
优点:
- 减少依赖:客户端只需依赖工厂类与产品基类,而不需要依赖具体产品类。
- 解耦创建与使用:工厂类封装了创建细节,客户端只负责使用产品。
-
缺点:
- 违反开闭原则:每次添加新的工具类型,必须修改工厂类的
CreateTool
方法,添加一条新的case:
,导致不符合 “对修改关闭,对扩展开放”的原则。在扩展性和代码维护上有一定的缺点,特别是在需要频繁添加新工具类型的情况下。 - 工厂类复杂化:工厂类会随产品种类的增加而变得复杂。
- 违反开闭原则:每次添加新的工具类型,必须修改工厂类的
1.2 工厂方法(Factory Method)
工厂方法模式通过将创建对象的逻辑推迟到子类中,从而解决简单工厂模式违反开闭原则的问题。它的核心理念是将工厂类拆分成多个具体工厂,每个工厂类负责创建某种特定产品。
核心结构
抽象产品 + 具体产品,抽象工厂 + 具体工厂
(1)示例
重构1.1中的示例代码,工具基类及其子类保持不变,但工厂类需要改造成每种产品对应一个工厂子类,各自负责产品的创建。
- 工厂类
ToolFactory.h
#pragma once #include <memory> #include "Tool.h"class ToolFactory { public:virtual std::unique_ptr<Tool> CreateTool() = 0;virtual ~ToolFactory() = default; };class DrawToolFactory : public ToolFactory { public:std::unique_ptr<Tool> CreateTool() override {return std::make_unique<DrawTool>();} };class EraseToolFactory : public ToolFactory { public:std::unique_ptr<Tool> CreateTool() override {return std::make_unique<EraseTool>();} };
- 客户端使用
main.cpp
#include "ToolFactory.h"int main() {// 创建绘制工具工厂对象std::unique_ptr<ToolFactory> drawFactory = std::make_unique<DrawToolFactory>();// 创建绘制工具std::unique_ptr<Tool> drawTool = drawFactory->CreateTool();if (drawTool)drawTool->UseTool();// 创建擦除工具工厂对象std::unique_ptr<ToolFactory> eraseFactory = std::make_unique<EraseToolFactory>();// 创建擦除工具std::unique_ptr<Tool> eraseTool = eraseFactory->CreateTool();if (eraseTool)eraseTool->UseTool();return 0; }
(2)总结
-
优点
- 符合开闭原则:新增产品时,只需新增对应的工厂类,而无需修改已有代码。
- 单一职责:每个工厂类只负责创建一种产品,职责更为明确。
- 可扩展性:更方便地增加新产品和新工厂,且代码修改局部化,减少潜在错误。
-
缺点
- 类的增加:每种产品都需要对应的工厂类,会导致类的数量增加,增加系统的复杂性。
- 复杂度提升:对于简单的对象创建场景,工厂方法模式可能显得过于复杂,因为每个具体产品都需要单独的工厂类。
- 职责分散:每个工厂类只负责创建某种具体产品,可能导致系统中存在较多分散的创建逻辑,维护起来可能不便。
1.3 抽象工厂(Abstract Factory)
在某些情况下,我们需要创建一组相关或依赖的对象,而不仅仅是单个对象。工厂方法模式虽然可以创建单个产品,但如果需要创建多个产品,并且这些产品之间存在某种强关联(比如 UI 系统中不同平台的按钮、文本框等,比如windows平台的按钮必须搭配同平台的文本框),工厂方法模式就显得不足了。
抽象工厂模式提供一个接口,用于创建相关联的对象族,而不指定它们的具体类。它解决了创建多类相关产品的问题,而不是单个产品。
核心结构:
- 抽象工厂类:定义创建一系列相关产品的接口。
- 具体工厂类:实现抽象工厂的接口,负责创建一系列具体产品。
- 抽象产品类:为不同产品提供统一的接口。
- 具体产品类:每个具体工厂创建的不同产品实现类。
- 客户端:通过抽象工厂接口来获取相关联的产品。
(1)示例
假设现在有4种具体工具产品,分别是2D绘制工具、2D擦除工具、3D绘制工具、3D擦除工具,正常情况来说,2D绘制工具跟2D擦除工具肯定是配套的,如果工厂方法来创建,就可能混淆使用,而抽象工厂则可以避免这种错误产生
-
Tool.h
:这里从Tool
接口类直接派生了4个工具,也可以这样做(根据需求灵活处理):- 定义
2DTool
抽象类和3DTool
抽象类,然后再分别派生2个具体工具类出来 - 定义
DrawTool
抽象类和EraseTool
抽象类,然后再分别派生2个具体工具类出来
#pragma once #include <iostream>// 抽象产品类 - 工具 class Tool { public:virtual void UseTool() = 0;virtual ~Tool() = default; };// 具体产品类 - 2D绘制工具 class Draw2DTool : public Tool { public:void UseTool() override {std::cout << "Using 2D Draw Tool!" << std::endl;} };// 具体产品类 - 2D擦除工具 class Erase2DTool : public Tool { public:void UseTool() override {std::cout << "Using 2D Erase Tool!" << std::endl;} };// 具体产品类 - 3D绘制工具 class Draw3DTool : public Tool { public:void UseTool() override {std::cout << "Using 3D Draw Tool!" << std::endl;} };// 具体产品类 - 3D擦除工具 class Erase3DTool : public Tool { public:void UseTool() override {std::cout << "Using 3D Erase Tool!" << std::endl;} };
- 定义
-
Factory.h
#pragma once #include <memory> #include "Tool.h"// 抽象工厂类 class ToolFactory { public:virtual std::unique_ptr<Tool> CreateDrawTool() = 0;virtual std::unique_ptr<Tool> CreateEraseTool() = 0;virtual ~ToolFactory() = default; };// 具体工厂类 - 2D工具工厂 class Tool2DFactory : public ToolFactory { public:std::unique_ptr<Tool> CreateDrawTool() override {return std::make_unique<Draw2DTool>();}std::unique_ptr<Tool> CreateEraseTool() override {return std::make_unique<Erase2DTool>();} };// 具体工厂类 - 3D工具工厂 class Tool3DFactory : public ToolFactory { public:std::unique_ptr<Tool> CreateDrawTool() override {return std::make_unique<Draw3DTool>();}std::unique_ptr<Tool> CreateEraseTool() override {return std::make_unique<Erase3DTool>();} };
-
main.cpp
// Main.cpp #include "Factory.h"int main() {// 创建2D工厂std::unique_ptr<ToolFactory> factory2D = std::make_unique<Tool2DFactory>();std::unique_ptr<Tool> tool = factory2D->CreateDrawTool();tool->UseTool(); tool = factory2D->CreateEraseTool();tool->UseTool(); // 创建3D工厂std::unique_ptr<ToolFactory> factory3D = std::make_unique<Tool3DFactory>();tool = factory3D->CreateDrawTool();tool->UseTool(); tool = factory3D->CreateEraseTool();tool->UseTool(); return 0; }
(2)总结
-
优点
- 产品族一致性:通过具体工厂类,确保了 2D 和 3D 工具的内部一致性,避免在客户端中创建不兼容的工具(如混用 2D 和 3D 工具)。
- 在新增工具方面,遵守开闭原则:新增其他绘制工具类型时,比如一个4D工具,只需额外实现新的具体工厂类和对应的产品类,保证了系统的可扩展性。
- 减少客户端依赖:客户端只依赖抽象工厂和抽象产品,而不需要关心具体实现的细节,符合依赖倒置原则。
-
缺点
- 复杂性:增加了工厂类和产品类的数量,系统结构更加复杂,尤其当产品族多时会造成一定的维护压力。
- 在新增每种工具的功能时,不遵守开闭原则:比如现在的每种工具套件都支持绘制、擦除工具,我还想新增一个修改工具,则需要修改每一个工厂类和每一个产品类的代码。
- 灵活性降低:所有工厂创建的产品都是预定义的,无法灵活组合不同种类的产品。
1.4 建造者(Builder)
建造者模式的作用是将复杂对象的组装过程和对象的实际表示区分开来。这样,相同的组装步骤可以用来制造出不同的对象表现形式。这种模式非常适合于那些由多个可选组件组成的复杂对象。通过分步骤地构建每个组件,我们可以根据需要灵活地组合出各种不同的对象。
建造者模式的核心理念是通过引入一个建造者(Builder)
类,负责构建对象的各个部分,而不是在一个复杂的构造函数中完成所有工作。它能够分阶段创建对象,允许客户端在构建过程中灵活选择和配置对象的组件。该模式还允许通过实现不同的具体建造者,来生成不同类型或版本的产品对象。
直接上具体案例,来理解这个模式
(1)示例
组装电脑,电脑有很多可定制的部件(如CPU、GPU、硬盘、内存等),对于不同的需求(比如游戏电脑、办公电脑),需要选用不同的性能、品牌的部件,建造者模式可以灵活地应对这些变化。
类之间的关系
Director
:通过Builder
来控制建造流程,确保每个步骤按顺序调用。它不需要知道具体的产品细节,只需要负责调用Builder
提供的接口。Builder
:定义了构建的接口,具体的建造步骤(如BuildCPU()
、BuildGPU()
等)。ConcreteBuilder
:实现Builder
接口的具体类,负责创建不同类型的产品,如游戏电脑和办公电脑。每个ConcreteBuilder
实现了相同的建造步骤,但生成不同的结果。Product
:是最终生成的对象,它包含了多个部分(CPU、GPU、Memory 等),由ConcreteBuilder
一步步构建。
#include <iostream>
#include <string>// 产品类:电脑
class Computer
{
public:void SetCPU(const std::string& cpu) { CPU = cpu; }void SetGPU(const std::string& gpu) { GPU = gpu; }void SetMemory(const std::string& memory) { Memory = memory; }void SetStorage(const std::string& storage) { Storage = storage; }void ShowSpecifications() const {std::cout << "Computer Specifications:\n";std::cout << "CPU: " << CPU << "\n";std::cout << "GPU: " << GPU << "\n";std::cout << "Memory: " << Memory << "\n";std::cout << "Storage: " << Storage << "\n";}private:std::string CPU;std::string GPU;std::string Memory;std::string Storage;
};// 抽象建造者:定义创建产品的步骤
class ComputerBuilder
{
public:virtual ~ComputerBuilder() = default;virtual void BuildCPU() = 0;virtual void BuildGPU() = 0;virtual void BuildMemory() = 0;virtual void BuildStorage() = 0;virtual Computer* GetResult() = 0;
};// 具体建造者:游戏电脑
class GamingComputerBuilder : public ComputerBuilder
{
private:Computer* computer;public:GamingComputerBuilder() {computer = new Computer();}~GamingComputerBuilder() {delete computer;}void BuildCPU() override {computer->SetCPU("i9");}void BuildGPU() override {computer->SetGPU("RTX4090 ");}void BuildMemory() override {computer->SetMemory("16GB DDR4");}void BuildStorage() override {computer->SetStorage("1TB SSD");}Computer* GetResult() override {return computer;}
};// 具体建造者:办公电脑
class OfficeComputerBuilder : public ComputerBuilder
{
private:Computer* computer;public:OfficeComputerBuilder() {computer = new Computer();}~OfficeComputerBuilder() {delete computer;}void BuildCPU() override {computer->SetCPU("i3");}void BuildGPU() override {computer->SetGPU("GTX 960");}void BuildMemory() override {computer->SetMemory("8GB DDR4");}void BuildStorage() override {computer->SetStorage("512GB SSD");}Computer* GetResult() override {return computer;}
};// 指挥者:控制建造流程
class Director
{
private:ComputerBuilder* builder = nullptr;
public:void SetBuilder(ComputerBuilder* builder) {this->builder = builder;}void Construct() {builder->BuildCPU();builder->BuildGPU();builder->BuildMemory();builder->BuildStorage();}
};// 客户端代码
int main()
{Director director;// 创建游戏电脑GamingComputerBuilder gamingBuilder;director.SetBuilder(&gamingBuilder);director.Construct();Computer* gamingComputer = gamingBuilder.GetResult();gamingComputer->ShowSpecifications();// 创建办公电脑OfficeComputerBuilder officeBuilder;director.SetBuilder(&officeBuilder);director.Construct();Computer* officeComputer = officeBuilder.GetResult();officeComputer->ShowSpecifications();delete gamingComputer;delete officeComputer;return 0;
}
(2)总结
-
优点:
-
灵活应对不同需求:在这个例子中,游戏电脑和办公电脑虽然都是由CPU、GPU、内存和硬盘等部件组成,但具体的配置差别很大。通过
Director
控制构建顺序,我们可以复用建造流程,但根据不同的 具体ConcreteBuilder
实现来生成不同的产品。这使得我们在不修改整体构建逻辑的情况下,可以灵活地创建多种不同的对象。 -
易扩展:建造者模式将复杂对象的构建过程与具体的构建实现解耦。
Director
只需要知道如何控制创建流程,具体怎么创建、用什么配置并不重要。通过这种解耦,可以很容易地替换或扩展新的ConcreteBuilder
,比如还可以再实现一个WorkstationComputerBuilder
,用于构建工作站电脑。 -
代码更加清晰:对于复杂对象的构建,通过一步步调用建造方法(如
BuildCPU()
、BuildMemory()
),构建过程非常清晰易懂。这种模式避免了构建过程中混乱的条件判断和冗长的构造代码。
-
-
缺点:
- 增加代码复杂度:模式引入了额外的建造者、指导者等类,可能会使代码量增多,结构变复杂。
- 多次构建成本高:如果每次构建都需要重建所有对象部分,可能导致性能开销。
相关文章:

C++设计模式(更新中)
文章目录 1、创建型模式1.1 简单工厂(Simple Factory)(1)示例(2)总结 1.2 工厂方法(Factory Method)(1)示例(2)总结 1.3 抽象工厂&…...

Kali crunsh字典工具
查看自带密码字典 vim /usr/share/wordlists 使用 crunch 字典工具 随机组成6位纯数字密码 crunch 6 6 0123456789 -o test1.txt 由 Abc1234 随机组成的 6~8 位密码 crunch 6 8 Abc1234 -o test2.txt 以A开头后面跟3位数字组成的4位密码 crunch 4 4 -t A%%% -o test3.txt...

Redis系列---Redission分布式锁
文章目录 类型原理使用看门狗与setNx比较 类型 使用Redission,lock的机制其实是使用了ttl,一直等ttl为0再get。无论是redission还是redis的setNx,只要是锁,都必须有加锁和释放锁两个动作,二者缺一不可,并且…...

算法打卡:第十一章 图论part05
今日收获:并查集理论基础,寻找存在的路径 1. 并查集理论基础(from代码随想录) (1)应用场景:判断两个元素是否在同一个集合中 (2)原理讲解:通过一个一维数组…...

3.《DevOps》系列K8S部署CICD流水线之部署MetalLB负载均衡器和Helm部署Ingress-Nginx
架构 服务器IP服务名称硬件配置192.168.1.100k8s-master8核、16G、120G192.168.1.101k8s-node18核、16G、120G192.168.1.102k8s-node28核、16G、120G192.168.1.103nfs2核、4G、500G操作系统:Rocky9.3 后续通过K8S部署GitLab、Harbor、Jenkins 为什么使用MetalLB 当使用云平…...

MySQL:表的约束
目录 1 空属性 2 默认值 3 列描述 4 zerofill 5 主键 6 自增长 7 唯一键 8 外键 真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。比如有…...

38.重复的子字符串
方法1: class Solution {public boolean repeatedSubstringPattern(String s) {if (s.equals("")) return false;String s2(ss).substring(1,(ss).length()-1);//去掉首尾字符return s2.contains(s);//判断是否包含s} } class Solution(object):def rep…...

Linux服务部署指南
在现代的IT基础设施中,Linux操作系统因其稳定性、安全性和灵活性而广泛用于服务部署。本文将提供一个全面的指南,介绍如何在Linux环境下部署服务,包括准备工作、部署流程、以及监控和维护。 1. 准备工作 在开始部署服务之前,确保…...

Unity中,如果你想让多个数字人轮流显示和隐藏
在Unity中,如果你想让多个数字人轮流显示和隐藏,可以通过控制它们的GameObject的激活状态 (SetActive()) 来实现。你可以创建一个简单的脚本来控制这些数字人的显示和隐藏,使用协程或者定时器来处理轮流的效果。 下面是一个基本的实现思路&a…...

【LeetCode】动态规划—删除并获得点数(附完整Python/C++代码)
动态规划—#740. 删除并获得点数 前言题目描述基本思路1. 问题定义:2. 理解问题和递推关系:3. 解决方法:4. 进一步优化:5. 小总结: 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 给你一个整数数组 n u m s nums nums ,你可以对它进行一…...

利用 PostgreSQL 构建 RAG 系统实现智能问答
在现代信息检索和自然语言处理的场景中,检索增强生成 (Retrieval-Augmented Generation, RAG) 系统因其结合了知识库检索和生成模型的优势,成为了一种非常流行的智能问答方法。在这篇博文中,我将展示如何利用PostgreSQL作为向量存储数据库&am…...

Go 并发模式:扩展与聚合的高效并行
当你搭建好一个管道系统后,数据在各个阶段之间顺畅地流动,并根据你设定的操作逐步转换。这一切看起来像是一条美丽的溪流,然而,为什么有时候这个过程会如此缓慢呢? 在处理数据时,某些阶段可能会非常耗时,导致上游的阶段被阻塞,无法继续处理数据。这不仅影响了管道的整…...

【Transformers基础入门篇2】基础组件之Pipeline
文章目录 一、什么是Pipeline二、查看PipeLine支持的任务类型三、Pipeline的创建和使用3.1 根据任务类型,直接创建Pipeline,默认是英文模型3.2 指定任务类型,再指定模型,创建基于指定模型的Pipeline3.3 预先加载模型,再…...

java反射学习总结
最近在项目上有一个内部的CR,运用到了反射。想起之前面试的时候被面试官追问有没有在项目中用过反射,以及反射的原理和对反射的了解。 于是借此机会,学习回顾一下反射,以及在项目中可能会用到的场景。 Java 中的反射概述 反射&…...

探索C语言与Linux编程:获取当前用户ID与进程ID
探索C语言与Linux编程:获取当前用户ID与进程ID 一、Linux系统概述与用户、进程概念二、C语言与系统调用三、获取当前用户ID四、获取当前进程ID五、综合应用:同时获取用户ID和进程ID六、深入理解与扩展七、结语在操作系统与编程语言的交汇点,Linux作为开源操作系统的典范,为…...

1.4 边界值分析法
欢迎大家订阅【软件测试】 专栏,开启你的软件测试学习之旅! 文章目录 前言1 定义2 选取3 具体步骤4 案例分析 本篇文章参考黑马程序员 前言 边界值分析法是一种广泛应用于软件测试中的技术,旨在识别输入值范围内的潜在缺陷。本文将详细探讨…...

Spring IOC容器Bean对象管理-注解方式
目录 1、Bean对象常用注解介绍 2、注解示例说明 1、Bean对象常用注解介绍 Component 通用类组件注解,该类被注解,IOC容器启动时实例化此类对象Controller 注解控制器类Service 注解业务逻辑类Respository 注解和数据库操作的类,如DAO类Reso…...

OpenAI API: How to catch all 5xx errors in Python?
题意:OpenAI API:如何在 Python 中捕获所有 5xx 错误? 问题背景: I want to catch all 5xx errors (e.g., 500) that OpenAI API sends so that I can retry before giving up and reporting an exception. 我想捕获 OpenAI API…...

C++初阶学习——探索STL奥秘——标准库中的priority_queue与模拟实现
1.priority_queque的介绍 1.priority_queue中文叫优先级队列。优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。 2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元…...

PyTorch经典模型
PyTorch 经典模型教程 1. PyTorch 库架构概述 PyTorch 是一个广泛使用的深度学习框架,具有高度的灵活性和动态计算图的特性。它支持自动求导功能,并且拥有强大的 GPU 加速能力,适用于各种神经网络模型的训练与部署。 PyTorch 的核心架构包…...

C++ STL容器(三) —— 迭代器底层剖析
本篇聚焦于STL中的迭代器,同样基于MSVC源码。 文章目录 迭代器模式应用场景实现方式优缺点 UML类图代码解析list 迭代器const 迭代器非 const 迭代器 vector 迭代器const 迭代器非const迭代器 反向迭代器 迭代器失效参考资料 迭代器模式 首先迭代器模式是设计模式中…...

力扣416周赛
举报垃圾信息 题目 3295. 举报垃圾信息 - 力扣(LeetCode) 思路 直接模拟就好了,这题居然是中等难度 代码 public boolean reportSpam(String[] message, String[] bannedWords) {Map<String,Integer> map new HashMap<>()…...

vue 页面常用图表框架
在 Vue.js 页面中,常见的用于制作图表的框架或库有以下几种: ECharts: 官方网站: EChartsECharts 是一个功能强大、可扩展的图表库,支持多种图表类型,如柱状图、折线图、饼图等。Vue 集成: 可以使用 vue-echarts 插件,…...

spring 注解 - @PostConstruct - 用于初始化工作
PostConstruct 是 Java EE 5 中引入的一个注解,用于标注在方法上,表示该方法应该在依赖注入完成之后执行。这个注解是 javax.annotation 包的一部分,通常用于初始化工作,比如初始化成员变量或者启动一些后台任务。 在 Spring 框架…...

多机器学习模型学习
特征处理 import os import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.model_selection import StratifiedShuffleSplit from sklearn.impute import SimpleImputer from sklearn.pipeline import FeatureUnion fr…...

【网页设计】前言
本专栏主要记录 “网页设计” 这一课程的相关笔记。 参考资料: 黑马程序员:黑马程序员pink老师前端入门教程,零基础必看的h5(html5)css3移动端前端视频教程_哔哩哔哩_bilibili 教材:《Adobe创意大学 Dreamweaver CS6标准教材》《…...

STM32巡回研讨会总结(2024)
前言 本次ST公司可以说是推出了7大方面,几乎可以说是覆盖到了目前生活中的方方面面,下面总结下我的感受。无线类 支持多种调制模式(LoRa、(G)FSK、(G)MSK 和 BPSK)满足工业和消费物联网 (IoT) 中各种低功耗广域网 (LPWAN) 无线应…...

54 螺旋矩阵
解题思路: \qquad 这道题可以直接用模拟解决,顺时针螺旋可以分解为依次沿“右-下-左-上”四个方向的移动,每次碰到“边界”时改变方向,边界是不可到达或已经到达过的地方,会随着指针移动不断收缩。 vector<int>…...

基于STM32与OpenCV的物料搬运机械臂设计流程
一、项目概述 本文提出了一种新型的物流搬运机器人,旨在提高物流行业的物料搬运效率和准确性。该机器人结合了 PID 闭环控制算法与视觉识别技术,能够在复杂的环境中实现自主巡线与物料识别。 项目目标与用途 目标:设计一款能够自动搬运物流…...

[万字长文]stable diffusion代码阅读笔记
stable diffusion代码阅读笔记 获得更好的阅读体验可以转到我的博客y0k1n0的小破站 本文参考的配置文件信息: AutoencoderKL:stable-diffusion\configs\autoencoder\autoencoder_kl_32x32x4.yaml latent-diffusion:stable-diffusion\configs\latent-diffusion\lsun_churches-ld…...