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

【iOS】工厂模式

文章目录

  • 前言
  • 设计模式的三大原则
  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式
  • 关于三兄弟的升级与降级
  • 注意


前言

上文讲完了iOS的架构模式,接下来聊一聊设计模式,设计模式有许多,主要介绍一下工厂模式

设计模式的三大原则

  • S 单一职责原则
    告诉我们实现类要职责单一;
    例如UIView负责处理事件传递响应,CALayer负责动画与视图的显示
  • O 开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;
// 基本的绘制类
@interface Shape : NSObject
- (void)draw;
@end// 扩展新的形状,无需修改现有代码
@interface Circle : Shape
@end@implementation Circle
- (void)draw {// 绘制圆形的逻辑
}
@end
  • L 里氏替换原则告诉我们不要破坏继承体系;
@interface Bird : NSObject
- (void)fly;
@end@interface Duck : Bird
@end@implementation Duck
- (void)fly {// 实现飞行
}
@end
  • D 迪米特法则。 一个对象应当对其他对象尽可能少的了解,实现高聚合、低耦合
// 班级类
@interface Class : NSObject
- (NSArray *)getAllStudents;
@end// 学校类
@interface School : NSObject
@property (strong, nonatomic) Class *class;
- (NSArray *)getAllStudentsInClass;
@end@implementation School
- (NSArray *)getAllStudentsInClass {return [self.class getAllStudents];
}
@end
  • I 接口隔离原则: 使用多个专门的协议、而不是一个庞大臃肿的协议
@protocol Printer
- (void)printDocument;
@end@protocol Scanner
- (void)scanDocument;
@end@interface MultiFunctionMachine : NSObject <Printer, Scanner>
@end@implementation MultiFunctionMachine
- (void)printDocument {// 打印文档
}- (void)scanDocument {// 扫描文档
}
@end
  • D 依赖倒置原则。抽象不应该依赖于具体实现、具体实现可以依赖于抽象。 调用接口感觉不到内部是如何操作的

定义协议(接口)

首先,我们定义一个文件读取的协议,这个协议负责声明读取文件内容的方法。

// FileReaderProtocol.h
#import <Foundation/Foundation.h>@protocol FileReaderProtocol <NSObject>
- (NSString *)readContent;
@end

具体实现类

接下来,实现这个协议。这里我们可以有多种实现方式,例如从本地文件系统读取,或是从网络获取。

// LocalFileReader.h
#import <Foundation/Foundation.h>
#import "FileReaderProtocol.h"@interface LocalFileReader : NSObject <FileReaderProtocol>
@property (strong, nonatomic) NSString *filePath;
- (instancetype)initWithFilePath:(NSString *)filePath;
@end// LocalFileReader.m
#import "LocalFileReader.h"@implementation LocalFileReader- (instancetype)initWithFilePath:(NSString *)filePath {self = [super init];if (self) {_filePath = filePath;}return self;
}- (NSString *)readContent {NSError *error;NSString *content = [NSString stringWithContentsOfFile:self.filePathencoding:NSUTF8StringEncodingerror:&error];if (error) {NSLog(@"Error reading file: %@", error.localizedDescription);return nil;}return content;
}@end

简单工厂模式

简单工厂模式并不是一个正式的设计模式,更多的是一种变成习惯
其主要通过传入参数给唯一的工厂类来创建不同类型的对象

但是这样就会出现一个问题,当我们需要添加新的类型,也就是添加新的产品时,我们必须去修改工厂类,这就违反了开闭原则

// 创建产品协议
@protocol Product <NSObject>
- (void)use;
@end// 具体产品A
@interface ProductA : NSObject <Product>
- (void)use;
@end@implementation ProductA
- (void)use {NSLog(@"Using Product A");
}
@end// 具体产品B
@interface ProductB : NSObject <Product>
- (void)use;
@end@implementation ProductB
- (void)use {NSLog(@"Using Product B");
}
@end// 简单工厂
@interface ProductFactory : NSObject
+ (id<Product>)productWithType:(NSString *)type;
@end@implementation ProductFactory
+ (id<Product>)productWithType:(NSString *)type {if ([type isEqualToString:@"A"]) {return [ProductA new];} else if ([type isEqualToString:@"B"]) {return [ProductB new];}return nil;
}
@end// 使用
ProductFactory *factory = [ProductFactory new];
id<Product> productA = [ProductFactory productWithType:@"A"];
[productA use];
// 首先创建一个工厂,根据传入的参数觉得工厂生产什么产品

在这里插入图片描述

工厂方法模式

工厂方法模式同样只是生产一种产品,但是一种产品可以有多个品牌

举个例子,我们的可乐工厂可以生产可乐,其即可以生产百事可乐,也可以生产可口可乐

首先我们需要定义一个创建对象的接口,但让子类决定要实例化的类是哪一个。工厂方法让类的实例化延迟到子类进行。
也就是抽象工厂是父类,具体工厂是子类,只有确定了具体工厂才能决定生产的产品是哪一种品牌的

// 定义产品接口
@protocol Logger <NSObject>
- (void)logMessage:(NSString *)message;
@end// 具体产品类 FileLogger
@interface FileLogger : NSObject <Logger>
- (void)logMessage:(NSString *)message;
@end@implementation FileLogger
- (void)logMessage:(NSString *)message {NSLog(@"File logger: %@", message);
}
@end// 具体产品类 NetworkLogger
@interface NetworkLogger : NSObject <Logger>
- (void)logMessage:(NSString *)message;
@end@implementation NetworkLogger
- (void)logMessage:(NSString *)message {NSLog(@"Network logger: %@", message);
}
@end// 抽象工厂类
@interface LoggerFactory : NSObject
- (id<Logger>)createLogger;
@end// 具体工厂类 FileLoggerFactory
@interface FileLoggerFactory : LoggerFactory
- (id<Logger>)createLogger;
@end@implementation FileLoggerFactory
- (id<Logger>)createLogger {return [[FileLogger alloc] init];
}
@end// 具体工厂类 NetworkLoggerFactory
@interface NetworkLoggerFactory : LoggerFactory
- (id<Logger>)createLogger;
@end@implementation NetworkLoggerFactory
- (id<Logger>)createLogger {return [[NetworkLogger alloc] init];
}
@end// 使用
LoggerFactory *factory;
if (useFileLogging) {factory = [[FileLoggerFactory alloc] init];
} else {factory = [[NetworkLoggerFactory alloc] init];
}
id<Logger> logger = [factory createLogger];
[logger logMessage:@"This is a test log."];

在这个例子中,LoggerFactory 是一个抽象类,定义了一个名为 createLogger 的方法,但并没有实现它。这个方法的具体实现由 FileLoggerFactoryNetworkLoggerFactory 这两个子类根据不同的业务逻辑来提供。这样,每个工厂子类决定了要实例化的具体 Logger 类,父类不需要知道具体的实现细节。

这种模式的优势在于,它支持易于扩展和修改的开放封闭原则,同时减少了类间的耦合。

我们再来看一个场景:
假设我们正在开发一个简单的绘图应用,该应用可以绘制不同类型的图形。我们可以使用工厂方法模式来创建不同类型的图形对象。

步骤 1: 定义图形接口和具体图形类。

// Shape.h
#import <Foundation/Foundation.h>@protocol Shape <NSObject>
- (void)draw;
@end// Circle.h
#import "Shape.h"@interface Circle : NSObject <Shape>
@end@implementation Circle
- (void)draw {NSLog(@"Drawing a circle.");
}
@end// Rectangle.h
#import "Shape.h"@interface Rectangle : NSObject <Shape>
@end@implementation Rectangle
- (void)draw {NSLog(@"Drawing a rectangle.");
}
@end

步骤 2: 定义抽象工厂类和具体工厂类。

// ShapeFactory.h
#import <Foundation/Foundation.h>
#import "Shape.h"@interface ShapeFactory : NSObject
- (id<Shape>)createShape;
@end// CircleFactory.h
#import "ShapeFactory.h"
#import "Circle.h"@interface CircleFactory : ShapeFactory
@end@implementation CircleFactory
- (id<Shape>)createShape {return [[Circle alloc] init];
}
@end// RectangleFactory.h
#import "ShapeFactory.h"
#import "Rectangle.h"@interface RectangleFactory : ShapeFactory
@end@implementation RectangleFactory
- (id<Shape>)createShape {return [[Rectangle alloc] init];
}
@end

步骤 3: 使用工厂类。

// main.m
#import <Foundation/Foundation.h>
#import "CircleFactory.h"
#import "RectangleFactory.h"int main(int argc, const char * argv[]) {@autoreleasepool {// 创建圆形工厂和矩形工厂ShapeFactory *circleFactory = [[CircleFactory alloc] init];ShapeFactory *rectangleFactory = [[RectangleFactory alloc] init];// 使用工厂方法创建形状id<Shape> circle = [circleFactory createShape];id<Shape> rectangle = [rectangleFactory createShape];// 绘制形状[circle draw];[rectangle draw];}return 0;
}

主程序依赖于抽象接口(Shape 协议和 ShapeFactory 类),而不是具体的类

我们来理解一下这句话

想象我们正在开发一个图形软件,软件需要支持多种类型图形,我们此时不需要知道操作的图形具体是什么,使用接口来定义这些操作,可以让你的软件支持任意类型的图形

定义抽象接口(如 Shape)

@protocol Shape <NSObject>
- (void)draw;
@end

实现具体类(如 Circle 和 Rectangle):

@interface Circle : NSObject <Shape>
@end@implementation Circle
- (void)draw {NSLog(@"Drawing a circle.");
}
@end@interface Rectangle : NSObject <Shape>
@end@implementation Rectangle
- (void)draw {NSLog(@"Drawing a rectangle.");
}
@end

CircleRectangle 类都实现了 Shape 协议,但具体的绘制逻辑根据图形的类型不同而不同。

抽象工厂模式

抽象工厂模式与工厂模式关键区别在于抽象工厂是用来创建一系列产品的,每个产品可以属于不同的产品类别,而工厂方法一般只创建一种产品。

场景:
假设我们有一个应用程序,需要支持多种界面风格,如“暗黑模式”和“亮色模式”,每种风格都有一套不同的界面组件(如按钮、文本框等)。我们可以使用抽象工厂模式来根据用户的选择动态提供相应的组件。

  • 步骤 1: 定义抽象产品和具体产品

首先,我们定义两种产品接口:Button 和 TextField,以及它们的具体实现。

// Button.h
@protocol Button <NSObject>
- (void)display;
@end// DarkButton.h
#import "Button.h"@interface DarkButton : NSObject <Button>
@end@implementation DarkButton
- (void)display {NSLog(@"Displaying dark button");
}
@end// LightButton.h
#import "Button.h"@interface LightButton : NSObject <Button>
@end@implementation LightButton
- (void)display {NSLog(@"Displaying light button");
}
@end// TextField.h
@protocol TextField <NSObject>
- (void)display;
@end// DarkTextField.h
#import "TextField.h"@interface DarkTextField : NSObject <TextField>
@end@implementation DarkTextField
- (void)display {NSLog(@"Displaying dark text field");
}
@end// LightTextField.h
#import "TextField.h"@interface LightTextField : NSObject <TextField>
@end@implementation LightTextField
- (void)display {NSLog(@"Displaying light text field");
}
@end
  • 步骤 2: 定义抽象工厂和具体工厂

定义一个抽象工厂接口,GUIFactory,以及为每种界面风格实现一个具体工厂。

// GUIFactory.h
#import "Button.h"
#import "TextField.h"@protocol GUIFactory <NSObject>
- (id<Button>)createButton;
- (id<TextField>)createTextField;
@end// DarkGUIFactory.h
#import "GUIFactory.h"
#import "DarkButton.h"
#import "DarkTextField.h"@interface DarkGUIFactory : NSObject <GUIFactory>
@end@implementation DarkGUIFactory
- (id<Button>)createButton {return [DarkButton new];
}
- (id<TextField>)createTextField {return [DarkTextField new];
}
@end// LightGUIFactory.h
#import "GUIFactory.h"
#import "LightButton.h"
#import "LightTextField.h"@interface LightGUIFactory : NSObject <GUIFactory>
@end@implementation LightGUIFactory
- (id<Button>)createButton {return [LightButton new];
}
- (id<TextField>)createTextField {return [LightTextField new];
}
@end
  • 步骤 3: 使用抽象工厂

客户端代码现在可以根据用户的偏好选择使用合适的工厂,而不需要关心具体的产品如何创建。

// main.m
#import <Foundation/Foundation.h>
#import "DarkGUIFactory.h"
#import "LightGUIFactory.h"int main(int argc, const char * argv[]) {@autoreleasepool {id<GUIFactory> factory;BOOL useDarkMode = YES;  // 用户选择使用暗黑模式if (useDarkMode) {factory = [[DarkGUIFactory alloc] init];} else {factory = [[LightGUIFactory alloc] init];}id<Button> button = [factory createButton];id<TextField> textField = [factory createTextField];[button display];[textField display];}return 0;
}

关于三兄弟的升级与降级

  • 单一类型产品比较少时,用简单工厂模式。
  • 单一类型产品各种定制比较多时,用工厂模式。
  • 多种类型产品时,使用抽象工厂模式。

注意

我们注意到定义产品类前我们通常会先定义一个抽象产品接口,也就是协议,例如:

// 定义产品接口
@protocol Logger <NSObject>
- (void)logMessage:(NSString *)message;
@end// 具体产品类 FileLogger
@interface FileLogger : NSObject <Logger>
- (void)logMessage:(NSString *)message;
@end

同时还有在主程序中创建对象

// 使用工厂方法创建形状id<Shape> circle = [circleFactory createShape];id<Shape> rectangle = [rectangleFactory createShape];

这就符合我们的依赖倒置原则

主程序依赖于抽象接口(Shape 协议和 ShapeFactory 类),而不是具体的类

相关文章:

【iOS】工厂模式

文章目录 前言设计模式的三大原则简单工厂模式工厂方法模式抽象工厂模式关于三兄弟的升级与降级注意 前言 上文讲完了iOS的架构模式&#xff0c;接下来聊一聊设计模式&#xff0c;设计模式有许多&#xff0c;主要介绍一下工厂模式 设计模式的三大原则 S 单一职责原则 告诉我…...

目标检测算法YOLOv6简介

YOLOv6由Chuyi Li等人于2022年提出&#xff0c;论文名为&#xff1a;《YOLOv6: A Single-Stage Object Detection Framework for Industrial Applications》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/2209.02976 &#xff0c;项目网页&#xff1a;https://github.c…...

如何修复显示器或笔记本电脑屏幕的黄色色调?这里提供几种方法

序言 如果你的笔记本电脑屏幕呈淡黄色,则可以启用夜灯功能。该问题也可能源于连接松散的显示电缆、损坏的显卡驱动程序或错误配置的显示器设置。以下是一些故障排除步骤,你可以尝试解决此问题。 禁用夜间模式 夜间模式功能旨在减少显示器的蓝色色调,使屏幕看起来更温暖,…...

5.14 力扣每日一题 贪心

2244. 完成所有任务需要的最少轮数 class Solution { public:int minimumRounds(vector<int>& tasks) {int ntasks.size(),sum0;sort(tasks.begin(),tasks.end()); //排序就不用哈希表int a;for(int i0;i<n;){int ct0;atasks[i];while(i<n&&tasks[i]a…...

wordpress 访问文章内容页 notfound

解决&#xff1a; 程序对应的伪静态规则文件.htaccess是空的 网站根目录下要有 .htaccess 文件&#xff0c;然后将下面的代码复制进去。 <ifmodule mod_rewrite.c>RewriteEngine OnRewriteBase /RewriteRule ^index\.php$ - [L]RewriteCond %{REQUEST_FILENAME} !-fRew…...

【Python探索之旅】列表

目录 特点 入门 访问元素 新增元素 修改元素 插入元素 删除元素 完结撒花 前言 在Python中&#xff0c;列表(List)是最常用的数据结构之一&#xff0c;类似于其他语言&#xff0c;如Java&#xff0c;与其不同啊Python中不需要声明数据类型。它提供了一种灵活且高效的方式…...

搜维尔科技:深入探讨Varjo XR头显在汽车行业的可能性

搜维尔科技&#xff1a;深入探讨Varjo XR头显在汽车行业的可能性 搜维尔科技&#xff1a;深入探讨Varjo XR头显在汽车行业的可能性...

YOLOv8预测流程-原理解析[目标检测理论篇]

接下来是我最想要分享的内容&#xff0c;梳理了YOLOv8预测的整个流程&#xff0c;以及训练的整个流程。 关于YOLOv8的主干网络在YOLOv8网络结构介绍-CSDN博客介绍了&#xff0c;为了更好地介绍本章内容&#xff0c;还是把YOLOv8网络结构图放在这里&#xff0c;方便查看。 1.前言…...

TCP超时重传机制

一、TCP超时重传机制简介 TCP超时重传机制是指当发送端发送数据后&#xff0c;如果在一定时间内未收到接收端的确认应答&#xff0c;则会认为数据丢失或损坏&#xff0c;从而触发重传机制。发送端会重新发送数据&#xff0c;并等待确认应答。如果在多次重传后仍未收到确认应答&…...

Oracle 的 RMAN(Recovery Manager) 和 DM(达梦数据库)的 DMRman异同

Oracle 的 RMAN&#xff08;Recovery Manager&#xff09; 和 DM&#xff08;达梦数据库&#xff09;的 DMRman异同 Oracle 的 RMAN&#xff08;Recovery Manager&#xff09; 和 DM&#xff08;达梦数据库&#xff09;的 DMRman 是两个分别用于不同数据库系统的备份和恢复工具…...

HVV面试题2024护网蓝队面试题

一. 目前有防火墙&#xff0c;全流量检测&#xff0c;态势感知&#xff0c;IDS&#xff0c;waf&#xff0c;web服务器等设备&#xff0c;如何搭建一个安全的内网环境&#xff0c;请给出大概拓扑结构 &#xff08;适用于中高级&#xff09; 搭建安全内网环境拓扑结构&#xff1…...

算法题--华为od机试考试(组成最大数、第k个排列、最小传输时延)

目录 组成最大数 题目描述 输入描述 输出描述 示例1 输入 输出 示例2 输入 输出 解析 答案 第k个排列 题目描述 输入描述 输出描述 示例1 输入 输出 示例2 输入 输出 解析 答案 最小传输时延 题目描述 输入描述 输出描述 示例1 输入 输出 解析…...

2024 年最新本地、云服务器安装部署 miniconda 环境详细教程(更新中)

Anaconda 概述 Anaconda 是专门为了方便使用 Python 进行数据科学研究而建立的一组软件包&#xff0c;涵盖了数据科学领域常见的 Python 库&#xff0c;并且自带了专门用来解决软件环境依赖问题的 conda 包管理系统。主要是提供了包管理与环境管理的功能&#xff0c;可以很方便…...

Python进行excel处理-01

最近干采购&#xff0c;每个月要对供应商的对账单&#xff0c;对对应的采购订单号和物料编号的价格和数量&#xff0c;是不是和物料管控总表里面的价格数量是不是一致&#xff0c;于是写了一个代码。 从总表里面找到&#xff0c;对账单里对应采购订单和物料编码的数据&#xf…...

苹果macOS无法给App麦克风授权解决办法

好久没有在电脑上录制课程了&#xff0c;有些东西还是录下来记忆深刻&#xff0c;却意外发现MAC系统升级后无法授权给第三方的App使用摄像头和麦克风&#xff0c;而录屏软件是需要开启麦克风和摄像头才能录制屏幕上的操作和声音&#xff0c;官方提示在第三方APP若有使用摄像头和…...

图的深度优先遍历

way&#xff1a;栈&#xff0c;map&#xff08;或set&#xff0c;只是我想用map&#xff09;记录是否访问过&#xff0c;放入时记录为已访问&#xff0c;打印&#xff0c;邻接的没访问过先入cur&#xff0c;再入邻接的节点&#xff0c;放入一个邻接的节点后及时break去下一个深…...

13 华三三层链路聚和

13 华三三层链路聚和 AI 解析 华三三层静态路由是指在华三交换机上配置的一种路由方式。它通过在交换机上手动配置路由表&#xff0c;将不同网络之间的数据进行转发。 华三三层静态路由的配置步骤如下&#xff1a; 1. 配置交换机接口的IP地址&#xff1a;在交换机上选择要配…...

C# 下载安装,使用OfficeOpenXml

下载安装OfficeOpenXml模块 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Reflection.Emit; using System.Text; using System.Text.RegularEx…...

Spring整体流程源码分析

DisableEncodeUrlFilter 防止sessionId被泄露 包装器模式 WebAsyncManagerIntegrationFilter WebAsyncManagerIntegrationFilter通常与Spring MVC的异步请求处理机制一起使用&#xff0c;确保在使用Callable或DeferredResult等异步处理方式时&#xff0c;安全上下文能够正…...

使用XxlCrawler抓取全球航空公司ICAO三字码

目录 前言 一、数据源介绍 1、目标网站 2、页面渲染结构 二、XxlCrawler信息获取 1、创建XxlCrawler对象 2、定义PageVo对象 3、直接PageVO解析 4、自定义解析 总结 前言 长距离旅行或者出差&#xff0c;飞机一定是出行的必备方式。对于旅行达人或者出差人员而言&…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...