工 厂 模 式
冷知识,当我们需要使用平底锅时,我们并不需要知道平底锅是怎么造的,坏了只需要再买就好了。至于造平底锅,全部交给我们的生产工厂就好。
蕴含这种创建对象思路的设计方法,我们称为“工厂模式”。
核心思想
工厂模式(Factory)是最常用的设计模式之一了,属于创建型,核心是将对象的创建过程与使用过程分离。它将对象的实例化封装在一个工厂类中,使客户端代码无需关心其构造细节。
工厂模式分为三类,简单工厂模式(Simple Factory),工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory),接下来将进行逐一讲解。
简单工厂模式
简单工厂模式特色就是简单粗暴,其可以根据传入参数的不同直接创建不同的对象。其又称为静态工厂模式,因为其通常用静态方法来创建对象,点开即用,避免重复。
在工厂这套“工厂体系”中,有三个角色需要我们实现:
1、抽象产品角色:是所有具体产品的基类或接口,统一接口规范,强制所有的基类实现相同的方法,确保客户端在使用时可以以统一的方式调用,隐藏实现细节。
2、具体产品角色:继承自抽象产品角色的具体实现类,提供特定类型对象的具体行为。这样一来就实现了多态,客户端代码只需要使用抽象产品而非具体产品,符合依赖倒置原则。
3、工厂角色:封装创建对象的逻辑,隔离客户端与具体类。
这里就以游戏开发中敌人的生成来举例吧。
#include <iostream>
using namespace std;
#include <string>
/*抽象产品角色*/
//定义接口
class Enemy {
public:
//统一行为:敌人攻击
virtual void Attack() = 0;
};
/*具体产品角色*/
class Goblin : public Enemy {
public:
//实现攻击
//(override显式声明重写基类虚函数)
void Attack() override {cout << "你被哥布林用双手拥抱住了!" << endl;}
};
class Slime : public Enemy {
public:
//实现攻击
void Attack() override {cout << "你被史莱姆用身体包裹住了!" << endl;}
};
/*工厂角色*/
class EnemyFactory {
public:
static Enemy* createEnemy(const string& name ) {
if (name == "Goblin") {
return new Goblin();}
else if (name == "Slime") {
return new Slime();}
else {cout << "没有生成敌人" << endl;
return NULL;}}
};
int main() {Enemy* A = EnemyFactory::createEnemy("Goblin");Enemy* B = EnemyFactory::createEnemy("Slime");A->Attack();B->Attack();
return 0;
}
简单工厂的优点就是简单,我们使用对象时只需要知道对应的参数就可以了,大大减少了记忆负担。工厂类也为我们完成了任务分工,我们什么也不用管。但是这样一来,所有产品的创建逻辑都集成在工厂类中,扩展困难,不具备开闭原则的优势。
工厂方法模式
刚刚说到,简单工厂模式想要扩展创建新的产品时,需要修改工厂类的内部逻辑,这违背了开闭原则。那么当我们将工厂类中创建不同产品的逻辑分别封装到一个个子类工厂中,那我们创建新产品时就只需要创建新的子类工厂即可,从而实现高效扩展。
这时有四个角色需要我们实现:
1、抽象产品角色:具体产品的基类,统一接口规范。
2、具体产品角色:定义具体行为。
3、抽象工厂角色:定义子类工厂实现的规范,由其派生出子类工厂,不负责具体实现。
4、具体工厂角色:为抽象工厂的子类工厂,实现具体对象的创建逻辑,每个具体工厂对应一个具体产品。
同样,这里就把刚刚的简单工厂改造为工厂方法吧。
#include <iostream>
using namespace std;
/*抽象产品*/
//定义接口
class Enemy {
public:
virtual void Attack() = 0;
virtual ~Enemy(){}
};
/*具体产品*/
class Goblin : public Enemy {
public:
void Attack() override {cout << "你被哥布林用双手拥抱住了!" << endl;}
};
class Slime : public Enemy {
public:
void Attack() override {cout << "你被史莱姆用身体包裹住了!" << endl;}
};
/*抽象工厂*/
class EnemyFactory {
public:
//子类工厂接口
virtual Enemy* createEnemy() = 0;
virtual ~EnemyFactory(){}
};
/*具体工厂*/
//哥布林工厂
class GoblinFactory : public EnemyFactory {
Enemy* createEnemy() override {
return new Goblin();}
};
//史莱姆工厂
class SlimeFactory : public EnemyFactory {
Enemy* createEnemy() override{
return new Slime();}
};
int main() {
//需要创建具体工厂对象EnemyFactory* goblin = new GoblinFactory();EnemyFactory* slime = new SlimeFactory();Enemy* A = goblin->createEnemy();Enemy* B = slime->createEnemy();A->Attack();B->Attack();
delete goblin;
delete slime;
delete A;
delete B;
return 0;
}
现在的话代码就完全符合开闭原则了,系统的可扩展性增强了。因为其具体工厂都有唯一的抽象基类,所以工厂方法模式又叫多态方法模式,用户无需关注类的细节,甚至不需要知道具体产品的类名。但从上面代码也能看出,每次编写新的具体产品类时,还需要提供新的具体工厂类,有些增加开销。
抽象工厂模式
我们现在知道了,工厂模式是关注单个产品的,比如敌人工厂,专门生成各种敌人。但是我们的游戏系统中一定不光是有敌人存在的,还有友人,路人(中立)等同类型级别的生物存在。这时,当系统需要生产一组相关联的复杂对象而非单个简单对象,且这些对象属于不同的产品类别,抽象工厂模式是最佳选择。
在抽象工厂模式中,我们需要引入“产品等级结构”与“产品族”的概念。
产品等级结构:产品等级结构即产品的继承结构,就是抽象产品类和各个具体产品类构成一个产品等级结构。如上图中,近战生物产品作为抽象父类,近战敌人、近战友人、近战路人作为具体子类,他们就构成一个产品等级结构。
产品族:由同一个工厂生产的位于不同产品等级结构的一组产品。比如上图中的敌人工厂生产的近战敌人、远攻敌人,属于一个产品族。
但是如果将上图敌人生成工厂与我们以前使用的哥布林、史莱姆的例子直接结合的话,会形成嵌套抽象工厂。但我们要知道抽象工厂的核心目标是管理一个产品族,否则会违背单一职责原则,使结构臃肿,所以通常采用其他设计方法。我们也可以看出当产品等级结构只有一个时,抽象工厂模式就会退化为工厂方法模式。
那么理解之后,我们继续修改上文中所使用的代码实现抽象工厂模式。现在需要知道每一个产品等级结构不需要同等级,而需要具有强关联性,比如说,我们要生产哥布林,就不能只生产哥布林,还有其武器、防具等强相关的属性。
#include <iostream>
using namespace std;/*产品等级结构1(抽象产品)——敌人*/
class Enemy {
public:virtual void Attack() = 0;virtual ~Enemy(){}
};
/*产品等级结构2(抽象产品)——武器*/
class Weapon {
public:virtual void Hold() = 0;virtual ~Weapon() {}
};
/*产品等级结构3(抽象产品)——防具*/
class Armor {
public:virtual void Dress() = 0;virtual ~Armor(){}
};
//划分完产品等级结构之后,开始定义具体产品,实现不同产品族
//产品族1:哥布林系列产品
/*具体产品(敌人)——哥布林特有(哥布林)*/
class Goblin : public Enemy {
public:void Attack() override {cout << "你被哥布林用双手拥抱住了!" << endl;}
};
/*具体产品(武器)——哥布林特有(木棍)*/
class Stick : public Weapon {
public:void Hold() override {cout << "它在使用木棍对付你!" << endl;}
};
/*具体产品(防具)——哥布林特有(肚兜)*/
class Bellyband : public Armor {
public:void Dress() override {cout << "别忘了它只穿了一个肚兜!" << endl;}
};
//产品族2:史莱姆系列产品
/*具体产品(敌人)——史莱姆特有(史莱姆)*/
class Slime : public Enemy {
public:void Attack() override {cout << "你被史莱姆用身体包裹住了!" << endl;}
};
/*具体产品(武器)——史莱姆特有(粘液)*/
class Mucus : public Weapon {
public:void Hold() override {cout << "它在使用粘液对付你!" << endl;}
};
/*具体产品(防具)——史莱姆特有(没穿)*/
class NoCloth : public Armor {
public:void Dress() override {cout << "别忘了它什么都没有穿哦!" << endl;}
};
/*抽象工厂*/
class EnemyFactory {
public://统一产品族的创建virtual Enemy* createEnemy() = 0;virtual Weapon* createWeapon() = 0;virtual Armor* createArmor() = 0;virtual ~EnemyFactory(){}
};
/*具体工厂——每个工厂对应一个产品族*/
//哥布林工厂
class GoblinFactory : public EnemyFactory {Enemy* createEnemy() override {return new Goblin();}Weapon* createWeapon() override {return new Stick();}Armor* createArmor() override {return new Bellyband();}
};
//史莱姆工厂
class SlimeFactory : public EnemyFactory {Enemy* createEnemy() override {return new Slime();}Weapon* createWeapon() override {return new Mucus();}Armor* createArmor() override {return new NoCloth();}
};int main() {//需要创建具体工厂对象EnemyFactory* goblin = new GoblinFactory();EnemyFactory* slime = new SlimeFactory();Enemy* enemyA = goblin->createEnemy();Enemy* enemyB = slime->createEnemy();Weapon* weaponA = goblin->createWeapon();Weapon* weaponB = slime->createWeapon();Armor* armorA = goblin->createArmor();Armor* armorB = slime->createArmor();enemyA->Attack();weaponA->Hold();armorA->Dress();enemyB->Attack();weaponB->Hold();armorB->Dress();delete goblin;delete slime;delete enemyA, enemyB, weaponA, weaponB, armorA, armorB;return 0;
}
这时,我们成功实现了抽象工厂模式,提供了一系列相关或相互依赖的对象的接口,隔离了具体类的生成。增加新的产品族和具体工厂时无需修改内部逻辑,符合开闭原则。缺点就是没办法直接添加新的产品对象,即新的产品等级结构。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。其常常用于以下场景:
1、需要创建一组相关或依赖的对象:这些产品通常都需要使用,比如敌人生成系统中,大家都有一套攻击方式、防御方式、移动方式等。
2、需要支持扩展产品族:比如创建新敌人”龙“的时候,正好也需要攻击方式、移动方式等一套模板式的行为。
3、系统不依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
4、属于同一个产品族的产品将在一起使用,协同工作。能够保证兼容性。
5、系统提供一个产品类的库(系统中一系列相关的产品类被组织为一个”库“,被抽象工厂管理),所有的产品以同样的接口出现,从而使客户端不依赖于具体实现(只和抽象接口交互)。
小结
在游戏开发中,工厂模式的使用十分广泛。比如宝箱中生成随机属性的药水,可以根据工厂中不同产品或产品族可以切换的特点从而随机生成。还有职业选择,根据法师、战士等不同的特点配套不同的模组。总的来说,工厂模式的核心在于解耦,将创建与使用分离,尤其适合统一管理一整套相关对象。
如有补充纠正欢迎各位留言。
相关文章:
工 厂 模 式
冷知识,当我们需要使用平底锅时,我们并不需要知道平底锅是怎么造的,坏了只需要再买就好了。至于造平底锅,全部交给我们的生产工厂就好。 蕴含这种创建对象思路的设计方法,我们称为“工厂模式”。 核心思想 工厂模式&…...
synchronized与Lock深度对比
Java并发编程:synchronized与Lock深度对比 基本概念 1.1 synchronized synchronized是Java内置的关键字,属于JVM层面的锁机制。它通过对象监视器(Monitor)实现同步,具有自动获取和释放锁的特性。 // 同步方法 public synchronized void sy…...
LeetCode —— 94. 二叉树的中序遍历
94. 二叉树的中序遍历 题目:94. 二叉树的中序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) :…...
【无标题】四色拓扑收缩模型中环形套嵌结构的颜色保真确定方法
#### **1. 环形嵌套结构的局部保真机制** - **零点虚边与环形嵌套**:在顶点 \( v \) 处引入环形嵌套结构(如环面 \( T^2 \)),通过虚边连接形成闭合路径。该结构作为“颜色记忆单元”,存储相邻区域的色彩信息࿰…...
Curl 全面使用指南
Curl(Client URL)是一个跨平台命令行工具,支持多种协议(HTTP/HTTPS/FTP/SFTP等),用于数据传输、API调试、文件上传/下载等场景。以下从 核心功能、用户疑问解答、高级技巧 三方面系统总结,并整合…...
vscode 的空格和 tab 设置 与 Rime 自建词库
自动保存(多用于失去焦点时保存) Files: Auto Save 推荐不勾 保存时格式化(Pritter 插件的功能,自动使用 Pritter 的格式) Editor: Format On Save 推荐不勾 tab 的空格数量,2 或 4 Editor: Tab Size 推荐…...
Spark-小练试刀
任务1:HDFS上有三份文件,分别为student.txt(学生信息表)result_bigdata.txt(大数据基础成绩表), result_math.txt(数学成绩表)。 加载student.txt为名称为student的RDD…...
Python爬虫实战:获取jd商城最新5060ti 16g显卡销量排行榜商品数据并做分析,为显卡选购做参考
一、引言 1.1 研究目的 本研究旨在利用 Python 爬虫技术,从京东商城获取 “5060ti 16g” 型号显卡的商品数据,并对这些数据进行深入分析。具体目标包括: 实现京东商城的模拟登录,突破登录验证机制,获取登录后的访问权限。高效稳定地爬取按销量排名前 20 的 “5060ti 16g…...
【Vue bug】:deep()失效
vue 组件中使用了 element-plus 组件 <template><el-dialog:model-value"visible":title"title":width"width px":before-close"onClose"><div class"container" :style"{height:height px}"&g…...
基于数字图像处理的裂缝检测与识别系统(Matlab)
【优化】Matlab裂缝检测与识别系统 基于数字图像处理的裂缝检测与识别系统(Matlab) (基本常在线秒回,有兴趣可以随时联系博主) 系统主要的内容包括: 1.图像加载与初始化 选择图像文件并加载:…...
day12:遗传算法及常见优化算法分享
遗传算法这些常见优化算法简直是 “宝藏素材”!用好了,轻轻松松就能填满论文一整节内容;要是研究透彻,甚至能独立撑起一整个章节。今天不打算深入展开,有个基础认知就行。等之后写论文真要用到这些算法了,咱…...
【计算机视觉】语义分割:MMSegmentation:OpenMMLab开源语义分割框架实战指南
深度解析MMSegmentation:OpenMMLab开源语义分割框架实战指南 技术架构与设计哲学系统架构概览核心技术特性 环境配置与安装指南硬件配置建议详细安装步骤环境验证 实战全流程解析1. 数据集准备2. 配置文件定制3. 模型训练与优化4. 模型评估与推理 核心功能扩展1. 自…...
25_04_30Linux架构篇、第1章_02源码编译安装Apache HTTP Server 最新稳定版本是 2.4.62
Linux_基础篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:源码编译安装Apache HTTP Server 最新稳定版本是 2.4.62 版本号: 1.0,0 作者: 老王要学习 日期: 2025.05.01 适用环境: Centos7 文档说明 本文…...
【重走C++学习之路】25、特殊类设计
目录 一、不能被拷贝的类 二、堆上创建对象的类 三、栈上创建对象的类 四、不能被继承的类 五、单例模式 结语 一、不能被拷贝的类 如何实现一个不能被拷贝的类?在看到这个要求的第一反应就是禁掉类的拷贝构造函数和赋值运算符重载函数,再往深了探…...
基于Redis实现-用户签到
基于Redis实现-用户签到 这个功能将使用到Redis中的BitMap来实现。 我们按照月来统计用户签到信息,签到记录为1,未签到则记录为0 把每一个bit位对应当月的每一天,形成了映射关系。用0和1标示业务状态,这种思路称为位图(BitMap)。…...
利用Redisson分布式锁解决多服务器数据刷新问题
利用Redisson分布式锁解决多服务器数据刷新问题 一、业务背景二、代码实现1、引入Redisson依赖2、配置Redisson,实际项目中Redis为集群配置3、自定义拒绝策略4、异步刷新网元服务 三、项目结构及源码 一、业务背景 最近有个需求需要自动刷新网元服务,由…...
25.4.30数据结构|并查集 路径压缩
前言 在QuickUnion快速合并的过程中,每次都要找根ID,而路径压缩让找根ID变得更加迅速直接。 路径压缩 针对的是findRootIndex()【查找根ID】进行的压缩。 需要实现的是: 在找根节点的过程中,记录这条路径上的所有信息,…...
react学习笔记3——基于React脚手架
React路由 相关理解 SPA的理解 单页Web应用(single page web application,SPA)。整个应用只有一个完整的页面。点击页面中的链接不会刷新页面,只会做页面的局部更新。数据都需要通过ajax请求获取, 并在前端异步展现。 路由的理…...
C#中的LINQ:简化数据查询与操作
引言 在现代软件开发中,处理和操作数据是不可避免的任务。无论是从数据库读取信息,还是对内存中的集合进行筛选、排序等操作,开发者都需要一种高效且易于使用的方法。C#中的LINQ(Language Integrated Query)正是为此而…...
OkHttp3.X 工具类封装:链式调用,支持HTTPS、重试、文件上传【内含常用设计模式设计示例】
OkHttp3.X 工具类封装:链式调用,支持HTTPS、重试、文件上传 基于OkHttp3.X封装,提供链式调用API,简化GET/POST请求,支持HTTPS、自动重试、文件上传等功能,提升开发效率。 在 Android 和 Java 开发中&#x…...
Unity SpriteEditor(精灵图片编辑器)
🏆 个人愚见,没事写写笔记 🏆《博客内容》:Unity3D开发内容 🏆🎉欢迎 👍点赞✍评论⭐收藏 🔎SpriteEditor: 精灵图片编辑器 📌用于编辑2D游戏开发中使用的Sp…...
雅思写作--70个高频表达
文章目录 1. learn new skills学生通过户外活动学到很多新技2. take immediate action to do各国采取有效行动以保护环境政府采取了必要行动以减少失业。你应该立即采取行动来解3. communication skills4. grow significantly5. have many advantages1. learn new skills “lea…...
Anaconda中配置Pyspark的Spark开发环境
Anaconda中配置Pyspark的Spark开发环境 目录 1.在控制台中测试ipython是否启动正常2.安装好Java3.安装Spark并配置环境变量4.PySpark配置5.修改spark\conf下的spark-env文件6.测试Pyspark是否安装成功 1.在控制台中测试ipython是否启动正常 anaconda正常安装 这里先检查ipyt…...
Spring 提供了多种依赖注入的方式
构造器注入(Constructor Injection) 构造器注入是通过类的构造函数来注入依赖项。这是 Spring 推荐的方式,因为它提供了不可变性和更好的可测试性。 import org.springframework.stereotype.Component;Component public class ServiceA {pub…...
面经-计算机网络——OSI七层模型与TCP/IP四层模型的对比详解
OSI七层模型与TCP/IP四层模型的对比详解 一、图示解析:分层封装结构 你提供的图清晰展示了网络通信中从应用层到物理层的封装过程,每一层都会对上层的数据加上自己的头部信息(Header): 应用层: 应用…...
网络安全知识问答微信小程序的设计与实现
网络安全知识问答微信小程序的设计与实现,说白了,就是搭建一款网络安全知识问答微信小程序,类似网络安全百科直通车。三步走。 需求沟通 进行需求沟通,此处省略1000字。 画草图 根据沟通的需求,进行整理,…...
Canvas特效实例:黑客帝国-字母矩阵(字母雨)
黑客帝国-字幕矩阵(字母雨) 效果预览代码实现思路解析遗留问题 效果预览 话不多说,我们直接上效果:当页面加载完成,屏幕上会落下如瀑布般的绿色字母流,不断向下滑动,仿佛进入了黑客帝国的数字世…...
「Mac畅玩AIGC与多模态11」开发篇07 - 使用自定义名言插件开发智能体应用
一、概述 本篇介绍如何在 macOS 环境下,通过编写自定义 OpenAPI Schema,将无需认证的名言服务接入 Dify 平台,并开发基于外部公共数据的智能体应用。本案例继续实践 GET 请求型 API 的实际调用技巧。 二、环境准备 1. 确认本地开发环境 macOS 系统Dify 平台已部署并可访问…...
快速上手非关系型数据库-MongoDB
简介 MongoDB 是一个基于文档的 NoSQL 数据库,由 MongoDB Inc. 开发。 NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。 MongoDB 的设计理念是为了应对大数据量、…...
响应式布局,在飞帆平台中如此简单
这些控件都是可以自己动手去实现的。也可以将这些控件复制到自己名下进行修改。 响应式布局https://fvi.cn/782...
UN R79 关于车辆转向装置形式认证的统一规定(正文部分1)
UN R79法规是针对转向装置的型式认证法规,涉及A/B1/C类的横向控制辅助驾驶功能,对各功能的功能边界、性能要求、状态提示、故障警示以及型式认证要提交的信息做了规范,本文结合百度文心一言对法规进行翻译,并结合个人理解对部分内…...
深度学习系统学习系列【1】之基本知识
文章目录 说明基础知识人工智能、机器学习、深度学习的关系机器学习传统机器学习的缺陷选择深度学习的原因深度学习的关键问题深度学习的应用深度学习的加速硬件GPU环境搭建主流深度学习框架对比 说明 文章属于个人学习笔记内容,仅供学习和交流。内容参考深度学习原…...
python3GUI--视频监控管理平台 By:PyQt5(详细讲解)
文章目录 一.前言二.相关知识1.PyQt52.RTSP协议📌 简介:🧩 特点:📡 工作方式: 2. **RTMP(Real-Time Messaging Protocol)**📌 简介:&a…...
第十一届蓝桥杯 2020 C/C++组 既约分数
目录 题目: 题目描述: 题目链接: 思路: 核心思路: 思路详解: 代码: 代码详解: 题目: 题目描述: 题目链接: 既约分数 - 蓝桥云课 思路&a…...
如何让Steam下载速度解除封印?!
平时一直没注意到家里的路由器在偷懒。最近成功榨干家里的带宽,把平时一直20mb/s左右下载速度的路由器一番改造后成功steam下载速度稳定85Mb/s。平时一直都只发挥了他的1/3不到,真是太可惜了。 硬件 首先检查硬件,就千兆路由器而言…...
HOOK上瘾思维模型——AI与思维模型【88】
一、定义 HOOK上瘾思维模型是一种通过设计一系列的触发(Trigger)、行动(Action)、奖励(Reward)和投入(Investment)环节,来促使用户形成习惯并持续使用产品或服务的思维框…...
基于开源AI智能名片链动2+1模式S2B2C商城小程序的IP开发泡沫破局与价值重构研究
摘要:当前IP开发领域普遍存在"冒进式泡沫"现象,企业将初级IP包装为超级IP运营,导致资源错配与价值虚化。本文通过实证分析开源AI智能名片链动21模式S2B2C商城小程序的技术架构与商业逻辑,揭示其通过智能内容引擎、合规化…...
深⼊理解指针(8)
1.对上一篇的补充内容 typedef int* ptr_t #define PTR_T int* 这两种写法都是可以的 ptr_t p1, p2; //p1, p2 都是指针变量 PTR_T p3, p4; //p3 是指针变量, p4是整型变量 为什么p3 是指针变量, p4是整型变量呢? 因为PTR_T 真的被改为了 int* 在编译器中…...
【iview】icon样式
A. 工程中引入样式文件 iview源码工程中的example工程中如何引入iview样式 image.png 自定义工程中如何引入iview样式 一般在src/main.js中引入(在index.html中也可以,当然app.vue中也可以) import "iview/dist/styles/iview.css"B…...
【计算机视觉】三维视觉:Nerfstudio:模块化神经辐射场框架的技术突破与实战指南
深度解析Nerfstudio:模块化神经辐射场框架的技术突破与实战指南 技术架构与核心创新系统架构设计关键技术特性 环境配置与安装指南硬件要求全平台安装流程 实战全流程解析1. 数据采集与预处理2. 模型训练与优化3. 可视化与导出 核心技术深度解析1. 混合表示网络2. 渐…...
第二章 OpenCV篇-图像阈值的综合操作-Python
目录 一.图像阈值 二.图像平滑 1.均值滤波 2.方框滤波 3.高斯滤波 4.中值滤波 5.双边滤波 此章节主要讲解:图像阈值、图像平滑处理、均值滤波、方框滤波、高斯滤波、中值滤波、双边滤波。 这里先讲作者使用matplotlib模块出现错误的解决方法。 首先作者在这…...
WPF处理大规模激光数据计算与安全传输处理
WPF大规模激光数据处理与安全传输系统设计方案 一、系统架构设计 1. 整体架构 ┌─────────────────────────────────────────────┐ │ WPF客户端应用 │ ├───────────────┬…...
vue 常见ui库对比(element、ant、antV等)
Element UI 1. 简介 Element UI 是一个基于 Vue 2 和 Vue 3 的企业级 UI 组件库,提供了丰富的组件和主题定制功能。官方网站:Element UI 2. 主要特点 丰富的组件:包括表单、表格、布局、导航、弹窗等多种组件。主题定制:支持主…...
【c++】【STL】stack详解
目录 stack类的作用什么是容器适配器stack的接口构造函数emptysizetoppushpopswap关系运算符重载 stack类的实现 stack类的作用 stack是stl库提供的一种容器适配器,也就是我们数据结构中学到的栈,是非常常用的数据结构,特点是遵循LIFO&#…...
单片机-89C51部分:12 pwm 呼吸灯 直流电机
飞书文档https://x509p6c8to.feishu.cn/wiki/JkzfwSoFBiUKc4kh8IoccTfyndg 一、什么是PWM? PWM是脉冲宽度调制的缩写,它是一种通过调整脉冲信号的高电平和低电平时间比例来控制电路输出的技术。简单来说,PWM是一种控制电子设备输出电压或电…...
WPF实现数据库操作与日志记录
1. 数据库操作实现 1.1 数据库连接基类 public abstract class DatabaseBase : IDisposable {protected string ConnectionString { get; }protected IDbConnection Connection { get; private set; }protected DatabaseBase(string connectionString){ConnectionString = co…...
用spring-boot-maven-plugin打包成单个jar有哪些缺点优化方案
Spring Boot 的 Fat JAR(通过 spring-boot-maven-plugin 打包)虽然简化了部署,但也存在一些潜在缺点,需根据场景权衡: 1. 启动速度较慢 原因: Fat JAR 需要在启动时解压并加载所有依赖的 JAR 文件到类路径…...
Spring Boot 使用 WebMagic 爬虫框架入门
1. 创建 Spring Boot 项目 使用 Spring Initializr 创建一个 Spring Boot 项目,选择需要的依赖,如 Spring Web 等。 2. 添加 WebMagic 依赖 在项目的 pom.xml 文件中添加 WebMagic 的核心和扩展依赖: <dependency><groupId>u…...
【软件设计师:复习】上午题核心知识点总结(二)
一、计算机网络(常考) 1.网络模型与协议(必考) 1.OSI七层模型 vs. TCP/IP四层模型 OSI七层TCP/IP四层核心协议/设备功能应用层(Application)应用层HTTP、FTP、DNS、SMTP提供用户接口和服务表示层(Presentation)SSL/TLS、JPEG、ASCII数据格式转换、加密/解密会话层(S…...
TensorRt10学习第一章
建立TensorRt时必须要有Public ILogger,因为createInferBuiler和createruntime要用,是一个接口 出错打印 和...