设计模式-工厂模式
设计模式 - 工厂模式
工厂模式(Factory Pattern)是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而使得一个类的实例化延迟到子类。工厂模式通过将对象创建的逻辑抽象化,减少了客户端代码与具体类之间的耦合。
工厂模式通常通过工厂类来实现,工厂类负责根据需求创建不同的对象。工厂模式常见的有以下几种变种:
- 简单工厂模式(Simple Factory Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
1. 简单工厂模式
- 定义:
简单工厂模式定义了一个工厂类,它根据不同的输入条件创建不同的产品类实例。客户端通过工厂类来获取所需的对象,而不需要关心对象是如何创建的。
示例:
假设我们有两种产品:ProductA 和 ProductB。客户端通过简单工厂来选择要创建的产品。
-
结构框图
-
代码实现
#include <iostream>// 产品基类
class Product {
public:// 纯虚函数 -> 实现多态(统一抽象化接口)virtual void showProduct() = 0;virtual ~Product() = default;
};// 具体产品A
class ConcreteProductA : public Product {
public:// 重写基类虚函数void showProduct() override {std::cout << "Create Product A" << std::endl;}
};// 具体产品B
class ConcreteProductB : public Product {
public:// 重写基类虚函数void showProduct() override {std::cout << "Create Product B" << std::endl;}
};// 简单工厂类, 用于去创建产品
class SimpleFactory {
public:Product* createProduct(char type) {if (type == 'A') {return new ConcreteProductA();} else if (type == 'B') {return new ConcreteProductB();} else {return nullptr;}}
};int main() {// 通过简单工厂创建产品SimpleFactory myfactory;// 利用简单工厂创建产品AProduct* productA = myfactory.createProduct('A');if(productA){productA->showProduct();}// 利用简单工厂创建产品BProduct* productB = myfactory.createProduct('B');if(productB){productB->showProduct();}delete productA;delete productB;return 1;
}
说明:
- 优点:客户端不需要知道具体类的实现,代码解耦。
- 缺点:随着产品种类的增加,工厂类变得越来越庞大,不符合开闭原则(对修改关闭,对扩展开放)。
2. 工厂方法模式(Factory Method Pattern)
- 定义:
- 封闭-开放 原则:新添加的功能不用去修改以前已经创建的类的内容
工厂方法模式将对象的创建推迟到子类,允许子类决定要创建的对象类型。通过定义一个抽象工厂接口,每个具体工厂只负责创建**一个**
特定类型的对象。
示例:
- 添加一个新的产品,只用新建其对应的产品类以及对于产品工厂类
将简单工厂模式中的产品创建移交给具体工厂类来实现。
-
结构框图
-
代码实现
#include <iostream>class Product
{
public:virtual void showProduct() = 0; // virtual ~Product() = default;
};class ConcreteProductA : public Product {
public:void showProduct() override{std::cout << "A product show (method factory)\n";}
};class ConcreteProductB : public Product {
public:void showProduct() override{std::cout << "B product show (method factory)\n";}
};// 工厂接口
class Factory {
public:virtual Product* createProduct(void) = 0;virtual ~Factory() = default;
};// 具体工厂A接口
class ConcreteFactoryA : public Factory {Product* createProduct(void) override{return new ConcreteProductA;}
};// 具体工厂B接口
class ConcreteFactoryB : public Factory {Product* createProduct(void) override{return new ConcreteProductB;}
};int main()
{Factory* factoryA = new ConcreteFactoryA;Factory* factoryB = new ConcreteFactoryB;Product* productA = factoryA->createProduct();Product* productB = factoryB->createProduct();productA->showProduct();productB->showProduct();delete factoryA;delete factoryB;delete productA;delete productB;return 1;
}
新添加一个产品C只用,添加ConcreteProductC
和ConcreteFactoryC
,但是不用去修改已经存在的类,符合封闭-开放原则的封闭原则。
- 说明:
- 优点:工厂方法模式将创建对象的工作推迟到子类,使得系统易于扩展,可以通过添加新的具体工厂来支持新产品。
- 缺点:每增加一种新产品,都需要增加一个新的工厂类,系统类的数量会迅速增加。
3. 抽象工厂模式(Abstract Factory Pattern)
定义:
抽象工厂模式提供一个接口,用于创建**一系列**
相关或依赖的对象,而无需指定它们具体的类。允许创建一组相关的对象(产品族),而每个具体的工厂都负责创建一组产品。常用于产品族的创建,即一组相互关联的对象的创建(比如跨平台 GUI 界面的不同风格)。
示例:
我们有两种平台(Windows 和 Linux),每个平台有不同的按钮和输入框。抽象工厂模式通过平台工厂来创建相应的控件。
#include <iostream>// 按钮接口
class Button {
public:virtual void render() = 0;virtual ~Button() = default;
};// 输入框接口
class TextField {
public:virtual void render() = 0;virtual ~TextField() = default;
};// 具体按钮类:Windows
class WindowsButton : public Button {
public:void render() override {std::cout << "Rendering Windows Button" << std::endl;}
};// 具体按钮类:Linux
class LinuxButton : public Button {
public:void render() override {std::cout << "Rendering Linux Button" << std::endl;}
};// 具体输入框类:Windows
class WindowsTextField : public TextField {
public:void render() override {std::cout << "Rendering Windows TextField" << std::endl;}
};// 具体输入框类:Linux
class LinuxTextField : public TextField {
public:void render() override {std::cout << "Rendering Linux TextField" << std::endl;}
};// 抽象工厂接口
class GUIFactory {
public:virtual Button* createButton() = 0;virtual TextField* createTextField() = 0;/*父类析构函数为虚函数的原因:在多态情况下正确地执行派生类的析构操作*/virtual ~GUIFactory() = default;
};// 具体工厂类:Windows
class WindowsFactory : public GUIFactory {
public:Button* createButton() override {return new WindowsButton();}TextField* createTextField() override {return new WindowsTextField();}
};// 具体工厂类:Linux
class LinuxFactory : public GUIFactory {
public:Button* createButton() override {return new LinuxButton();}TextField* createTextField() override {return new LinuxTextField();}
};int main() {GUIFactory* factory = new WindowsFactory();Button* button = factory->createButton();TextField* textField = factory->createTextField();button->render(); // 输出: Rendering Windows ButtontextField->render(); // 输出: Rendering Windows TextFielddelete button;delete textField;delete factory;factory = new LinuxFactory();button = factory->createButton();textField = factory->createTextField();button->render(); // 输出: Rendering Linux ButtontextField->render(); // 输出: Rendering Linux TextFielddelete button;delete textField;delete factory;return 0;
}
说明:
- 优点:能够
**创建一系列**
相关的产品,客户端不需要知道具体类的实现,只需依赖工厂接口。 - 缺点:增加了接口和类的数量,如果产品种类过多,抽象工厂可能变得复杂。
4. 工厂方法模式与抽象工厂模式的区别
特性 | 工厂方法模式(Factory Method) | 抽象工厂模式(Abstract Factory) |
---|---|---|
创建对象的方式 | 每个工厂方法只负责创建一个具体产品。 | 创建一系列相关或依赖的产品,通常创建多个产品。 |
产品的数量 | 通常每个工厂类创建一个产品。 | 每个工厂类负责创建多个产品(一个产品族)。 |
工厂的数量 | 每个具体工厂类负责创建一个特定的产品。 | 每个具体工厂类负责创建一系列相关的产品。 |
产品的关系 | 产品之间没有严格的依赖关系。 | 产品之间通常有一定的关联,属于同一个产品族(如同一平台下的按钮和文本框)。 |
扩展性 | 新产品需要新建一个工厂类来负责创建它。 | 新产品族需要新建一个工厂类来创建一组相关产品。 |
适用场景 | 产品种类不多时,或者系统只需要创建单一类型的对象时。 | 当需要创建多个相关产品时,尤其是多个产品属于同一产品族时。 |
总结:
- 工厂方法模式关注于**
单一产品
**的创建,每个具体工厂负责创建一个特定的产品。适用于产品种类少且扩展简单的场景。 - 抽象工厂模式关注于**
一系列相关产品
**的创建,每个具体工厂负责创建多个相关的产品,适用于需要创建多个相关对象并保证它们兼容的场景,如跨平台的 UI 库。
两者的主要区别在于创建产品的数量和产品之间的关系,工厂方法模式偏向于单一产品的创建,而抽象工厂模式偏向于创建一系列相关的产品。
相关文章:
设计模式-工厂模式
设计模式 - 工厂模式 工厂模式(Factory Pattern)是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而使得一个类的实例化延迟到子类。工厂模式通过将对象创建的逻辑抽象化…...
基于opencv的HOG+角点匹配教程
1. 引言 在计算机视觉任务中,特征匹配是目标识别、图像配准和物体跟踪的重要组成部分。本文介绍如何使用 HOG(Histogram of Oriented Gradients,方向梯度直方图) 和 角点检测(Corner Detection) 进行特征匹…...
《深度学习》——调整学习率和保存使用最优模型
调整学习率 在使用 PyTorch 进行深度学习训练时,调整学习率是一个重要的技巧,合适的学习率调整策略可以帮助模型更好地收敛。 PyTorch 提供了多种调整学习率的方法,下面将详细介绍几种常见的学习率调整策略及实例代码: torch.opt…...
Ubuntu22.04配置cuda/cudnn/pytorch
Ubuntu22.04配置cuda/cudnn/pytorch 安装cuda官网下载.run文件并且安装/etc/profile中配置cuda环境变量 cudnn安装官网找cuda版本对应的cudnn版本下载复制相应文件到系统文件中 安装pytorch官网找cuda对应版本的pytorchpython代码测试pytorch-GPU版本安装情况 安装cuda 官网下…...
通俗理解-L、-rpath和-rpath-link编译链接动态库
一、参考资料 链接选项 rpath 的应用和原理 | BewareMyPower的博客 使用 rpath 和 rpath-link 确保 samba-util 库正确链接-CSDN博客 编译参数-Wl和rpath的理解_-wl,-rpath-CSDN博客 Using LD, the GNU linker - Options Directory Options (Using the GNU Compiler Colle…...
【Golang】GC探秘/写屏障是什么?
之前写了 一篇【Golang】内存管理 ,有了很多的阅读量,那么我就接着分享一下Golang的GC相关的学习。 由于Golang的GC机制一直在持续迭代,本文叙述的主要是Go1.9版本及以后的GC机制,该版本中Golang引入了 混合写屏障大幅度地优化了S…...
Linux(Centos 7.6)命令详解:head
1.命令作用 将每个文件的前10行打印到标准输出(Print the first 10 lines of each FILE to standard output) 2.命令语法 Usage: head [OPTION]... [FILE]... 3.参数详解 OPTION: -c, --bytes[-]K,打印每个文件的前K字节-n, --lines[-],打印前K行而…...
【工具变量】上市公司网络安全治理数据(2007-2023年)
网络安全是国家安全体系的重要组成部分,是确保金融体系稳定运行、维护市场信心的关键。网络安全治理是指通过一系列手段和措施,维护网络安全,保护网络环境的稳定和安全,旨在确保公司网络系统免受未经授权的访问、攻击和破坏&#…...
watermark解释
在 Apache Flink 中,Watermark 是处理事件时间(Event Time)的核心机制,用于解决流处理中因数据乱序或延迟到达而导致的窗口计算不准确问题。理解 Watermark 的关键在于以下几点: 1. 事件时间 vs. 处理时间 事件时间&…...
Transformer 模型介绍(四)——编码器 Encoder 和解码器 Decoder
上篇中讲完了自注意力机制 Self-Attention 和多头注意力机制 Multi-Head Attention,这是 Transformer 核心组成部分之一,在此基础上,进一步展开讲一下编码器-解码器结构(Encoder-Decoder Architecture) Transformer 模…...
Linux安装Minio
1、下载rpm包 2、rpm 安装 rpm -ivh xx.rpm3、通过查看minion状态,查看其配置文件位置 systemctl start minio可以根据情况自定义修改配置文件内容,这里暂时不做修改 4、创建数据文件和日志文件,一般在/usr/local/ 5、编写启动脚本 #!/bi…...
JAVA EE初阶 - 预备知识(三)
一、中间件 中间件是一种处于操作系统和应用程序之间的软件,它能够为分布式应用提供交互、资源共享、数据处理等功能,是现代软件架构中不可或缺的一部分。下面从多个方面为你详细介绍中间件: 定义与作用 定义:中间件是连接两个或…...
百度热力图数据获取,原理,处理及论文应用6
目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历1.3、看天气 2、百度热力图几天够研究?部分文章统计3、数据原理3.1.1 ** 这个比较重要,后面还会再次出现。核密度的值怎么理解?**3.1.2 Csv->…...
tcp连接的11种状态及常见问题。
tcp链接整体流程,如下图所示: TCP协议在连接的建立和终止过程中涉及11种状态,这些状态反映了连接的不同阶段。以下是每种状态的详细说明: 1. CLOSED 初始状态,表示没有活动的连接或连接已完全关闭。当应用程序关闭连…...
宝塔面板开始ssl后,使用域名访问不了后台管理
宝塔面板后台开启ssl访问后,用的证书是其他第三方颁发的证书 再使用 域名/xxx 的形式:https://域名:xxx/xxx 访问后台,结果出现如下,不管使用 http 还是 https 的路径访问都进不后台管理 这个时候可以使用 https://ip/xxx 的方式来…...
5.日常英语笔记
sprouted tater 发芽的土豆 fluid 液体,流体 The doctor recommended drinking plenty of fluids 医生建议多喝流质 适应新环境 adapt to the new environment adjust to the new surroundings get used to the new setting accommodate oneself to the new circu…...
利用工业相机及多光谱图像技术助力医疗美容皮肤AI检测方案
随着年轻人对皮肤的管理要求越来越高,“科技护肤”已成为线下医疗美业护肤行业转型升级之趋势。如何利用先进的图像识别技术和AI大数据分析,为医生和消费者提供个性化的皮肤诊断分析和护肤建议,利用工业相机及多光谱成像技术完美实现这一可能…...
qt QOpenGLTexture详解
1. 概述 QOpenGLTexture 是 Qt5 提供的一个类,用于表示和管理 OpenGL 纹理。它封装了 OpenGL 纹理的创建、分配存储、绑定和设置像素数据等操作,简化了 OpenGL 纹理的使用。 2. 重要函数 构造函数: QOpenGLTexture(const QImage &image,…...
【Zookeeper如何实现分布式锁?】
Zookeeper如何实现分布式锁? 一、ZooKeeper分布式锁的实现原理二、ZooKeeper分布式锁的实现流程三、示例代码四、总结一、ZooKeeper分布式锁的实现原理 ZooKeeper是一个开源的分布式协调服务,它提供了一个分布式文件系统的接口,可以用来存储和管理分布式系统的配置信息。 …...
mysql 学习16 视图,存储过程,存储函数,触发器
视图, 存储过程, 存储函数 触发器...
(前端基础)HTML(一)
前提 W3C:World Wide Web Consortium(万维网联盟) Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括:机构化标准语言(HTML、XML) 表现标准语言(CSS) 行为标准…...
go设置镜像代理
前言 在 Go 开发中,如果直接从官方源(https://proxy.golang.org)下载依赖包速度较慢,可以通过设置 镜像代理 来加速依赖包的下载。以下是增加 Go 镜像代理的详细方法: 一、设置 Go 镜像代理 1. 使用环境变量设置代理…...
matlab数据处理:创建网络数据
% 创建网格数据 [X, Y] meshgrid(x_data, y_data); 如 x_data [1 2 3 4] X 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 XY_data [X(:), Y(:)]; % 将X和Y合并成一个向量 X(:)表示将矩阵排成一列 XY_data 1 …...
在企业内部私有化部署 DeepSeek 或其他 AI 大模型时,基于一般场景的最低硬件配置建议
1. 中央处理器(CPU) 核心数:至少 4 核心,支持多线程任务。频率:至少 2.5 GHz。CPU 型号:Intel Core i5 或更高(如 i7 或 i9),或 AMD Ryzen 5000 系列以上。多核支持&…...
DeepSeek 助力 Vue 开发:打造丝滑的颜色选择器(Color Picker)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
【ArcGIS Pro二次开发】(87):样式_Style的用法
.Stylx类型的文件即为样式库文件,保存了符号样式。 1、根据名字获取当前工程中的style //获取当前工程中的所有style var ProjectStyles Project.Current.GetItems<StyleProjectItem>();//根据名字找出指定的style StyleProjectItem style ProjectStyles.F…...
Jetson Agx Orin平台JP6.0-r36.3版本修复了vi模式下的原始图像损坏(线条伪影)
1.问题描述 这是JP-6.0 GA/ l4t-r36.3.0的一个已知问题 通过vi模式捕获的图像会导致异常线条 参考下面的快照来演示这些线伪影 这个问题只能通过VI模式进行修复,不应该通过LibArgus看到。 此外,这是由于内存问题。 由于upstream已经将属性名称更改为“dma-noncoherent”…...
nlp|微调大语言模型初探索(2),训练自己的聊天机器人
前言 上篇文章记录了具体的微调语言大模型步骤,以及在微调过程中可能遇见的各种报错,美中不足的是只是基于开源数据集的微调,今天来记录一下怎么基于自己的数据集去微调大语言模型,训练自己的智能机器人!!&…...
如何搭建Wi-Fi CVE漏洞测试环境:详细步骤与设备配置
引言 随着Wi-Fi技术的普及,Wi-Fi网络成为了现代通信的重要组成部分。然而,Wi-Fi网络的安全性始终是一个备受关注的话题。通过漏洞扫描和安全测试,网络管理员可以及早发现并修复Wi-Fi设备中存在的安全隐患。本篇文章将详细介绍如何搭建Wi-Fi …...
【三维重建】FeatureGS:特征值优化的几何精度和伪影减少3DGS的重构
文章:https://arxiv.org/pdf/2501.17655 标题:FeatureGS: Eigenvalue-Feature Optimization in 3D Gaussian Splatting for Geometrically Accurate and Artifact-Reduced Reconstruction 文章目录 摘要一、引言二、相关工作:3D特征三、算法3…...
请解释一下Standford Alpaca格式、sharegpt数据格式-------deepseek问答记录
1 Standford Alpaca格式 json格式数据。Stanford Alpaca 格式是一种用于训练和评估自然语言处理(NLP)模型的数据格式,特别是在指令跟随任务中。它由斯坦福大学的研究团队开发,旨在帮助模型理解和执行自然语言指令。以下是该格式的…...
WPS的AI助手进化跟踪(灵犀+插件)
Ver V0.0 250216: 如何给WPS安装插件用以支持其他大模型LLM V0.1 250217: WPS的灵犀AI现在是DeepSeek R1(可能是全参数671B) 前言 WPS也有内置的AI,叫灵犀,之前应是自已的LLM模型,只能说是属于“能用,有好过无”,所…...
本地事务简介
本地事务简介 1 事务基本性质 数据库事务的几个特性:原子性(Automicity)、一致性(Consistency)、隔离性或独立性(islation)和持久性(Durability),简称ACID。 原子性:一系列的操作,其整体不可拆分,要么同时成功&#…...
Python入门全攻略(七)
面向对象-基础 类和对象 类是一个抽象的概念,对象是一个具体的概念。类是对象的模板和蓝图,用来定义对象的属性和方法,对象是类的实例,具有具体的属性和行为。 类的定义 使用class关键字加上类名来定义类,在类的代码块中,我们可以写一些函数,这些函数是对一类对象共…...
SpringBoot 统一功能处理之拦截器、数据返回格式、异常处理
目录 拦截器 一、什么是拦截器 二 拦截器的使用 三 拦截路径配置 四 拦截器的执行流程 统一数据返回格式 统一异常处理 拦截器 一、什么是拦截器 拦截器是Spring框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法前后,根据业务…...
Javascript网页设计案例:通过PDF.js实现一款PDF阅读器,包括预览、页面旋转、页面切换、放大缩小、黑夜模式等功能
前言 目前功能包括: 切换到首页。切换到尾页。上一页。下一页。添加标签。标签管理页面旋转页面随意拖动双击后还原位置 其实按照自己的预期来说,有很多功能还没有开发完,配色也没有全都搞完,先发出来吧,后期有需要…...
js考核第三题
题三:随机点名 要求: 分为上下两个部分,上方为显示区域,下方为控制区域。显示区域显示五十位群成员的学号和姓名,控制区域由开始和结束两个按钮 组成。点击开始按钮,显示区域里的内容开始滚动,…...
新型基于Go语言的恶意软件利用Telegram作为C2通信渠道
研究人员发现了一种新型后门恶意软件,使用Go语言编写,并利用Telegram作为其命令与控制(C2)通信渠道。尽管该恶意软件似乎仍处于开发阶段,但它已经具备完整的功能,能够执行多种恶意活动。这种创新的C2通信方…...
【Python 语法】Python 正则表达式(regular expressions, regex)
1. 基本语法1.1 字符匹配1.2 元字符1.3 特殊字符1.4 分组和捕获1.5 断言2. 常用函数2.1 `re.match()`2.2 `re.search()`2.3 `re.findall()`2.4 `re.sub()`2.5 `re.split()`3. 进阶用法3.1 捕获组3.2 非捕获组3.3 预查Python 中的**正则表达式(regular expressions, regex)**是…...
STM32 如何使用DMA和获取ADC
目录 背景 摇杆的原理 程序 端口配置 ADC 配置 DMA配置 背景 DMA是一种计算机技术,允许某些硬件子系统直接访问系统内存,而不需要中央处理器(CPU)的介入,从而减轻CPU的负担。我们可以通过DMA来从外设…...
【原创】vue-element-admin-plus完成编辑页面中嵌套列表功能
前言 vue-element-admin-plus对于复杂业务的支持程度确实不怎么样,我这里就遇到了编辑页面中还要嵌套列表的真实案例,比如字典,主字典嵌套子信息,类似于一个树状结构。目前vue-element-admin-plus给出的例子是无法满足这个需求的…...
Java零基础入门笔记:(3)程序控制
前言 本笔记是学习狂神的java教程,建议配合视频,学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类&…...
拷打,数据库面经!
数据库必会面试题 1. 请解释数据库中的MVCC(多版本并发控制)机制,并说明其在MySQL InnoDB中的具体实现方式? 答案: MVCC是一种通过维护数据的历史版本实现高并发的技术,允许读操作不阻塞写操作࿰…...
Docker+DockerCompose+Harbor安装
安装docker # 安装yum工具 yum install yum-utils -y# 配置yum源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 安装docker yum install -y docker-ce-25.0.3 docker-ce-cli-25.0.3 containerd.io# 加载镜像 systemctl d…...
论文笔记(七十二)Reward Centering(一)
Reward Centering(一) 文章概括摘要1 奖励中心化理论 文章概括 引用: article{naik2024reward,title{Reward Centering},author{Naik, Abhishek and Wan, Yi and Tomar, Manan and Sutton, Richard S},journal{arXiv preprint arXiv:2405.0…...
在springboot加vue项目中加入图形验证码
后端 首先先要创建一个CaptchaController的类,可以在下面的代码中看到 在getCaptcha的方法里面写好了生成随机的4位小写字母或数字的验证码,然后通过BufferedImage类变为图片,顺便加上了干扰线。之后把图片转为Base64编码方便传给前端 为了…...
【系列专栏】银行IT的云原生架构-存储架构-数据库部署 10
银行 IT 的云原生架构:存储架构(数据库部署) 一、引言 在银行 IT 云原生架构的构建中,存储架构作为关键支撑,其性能、可靠性和扩展性直接影响着银行各类业务系统的运行效率与数据安全。而数据库作为数据存储与管理的…...
OpenGL ES -> 投影变换矩阵完美解决绘制GLSurfaceView绘制图形拉伸问题
GLSurfaceView绘制图形拉伸问题 假如在XML文件中声明GLSurfaceView的宽高为 android:layout_width"match_parent"android:layout_height"match_parent GLSurfaceView绘制的图形在Open GL ES坐标系中,而Open GL ES坐标系会根据GLSurfaceView的宽高将…...
【Three.js】JS 3D library(一个月进化史)
#春节过完了,该继续投入学习了~ 作为一个平面开发者,想要增进更多的技能,掌握web3D开发# 前置知识与技能 1. JavaScript 基础 - 掌握ES6语法(类、模块、箭头函数、解构等) - 熟悉异步编程(Promise、…...
在 debian 12 上安装 mysqlclient 报错
报错如下 Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting mysqlclientUsing cached https://pypi.tuna.tsinghua.edu.cn/packages/61/68/810093cb579daae426794bbd9d88aa830fae296e85172d18cb0f0e5dd4bc/mysqlclient-2.2.7.tar.gz (91 kB)Installi…...