深入浅出JavaScript常见设计模式:从原理到实战(1)
深入浅出JavaScript常见设计模式:从原理到实战(1)
设计模式是一种在特定情境下解决软件设计中常见问题的通用方案或模板。在特定的开发场景中使用特定的设计模式,可以提升代码质量,增强代码可读性和可维护性,提高团队开发效率,降低软件设计的复杂度。本文将介绍前端开发中常用的设计模式,讲解他们的含义,核心特性,使用场景及注意事项
一、设计模式核心认知
1.1 什么是设计模式
- 定义:经过验证的代码组织最佳实践方案
- 黄金三角:
- 场景:特定问题的解决方案
- 结构:类/对象的关系拓扑
- 效果:可维护性/扩展性提升
1.2 为什么需要设计模式
- 代码腐化防控:减少面条式代码
- 架构清晰度:提高模块化程度(示例:React Hooks vs Class组件)
- 团队协作:统一代码交流语言
二、4大高频设计模式详解
2.1 单例模式(Singleton)
单例模式(Singleton Pattern)是创建型设计模式中最基础且常用的模式之一,其核心目的是保证一个类仅有一个实例,并提供一个全局访问点供其他对象使用。以下是其关键要点:
核心特性
特性 | 说明 |
---|---|
唯一实例 | 单例类在任何情况下只能生成一个对象实例 |
自我创建 | 单例类需自行创建该唯一实例,通常通过私有化构造函数实现 |
全局访问 | 通过静态方法(如getInstance() )提供全局访问入口 |
延迟初始化 | 实例仅在首次请求时创建(可选特性,避免资源浪费) |
应用场景
-
系统配置管理
- 全局配置文件读取(避免重复加载)
- 应用主题/语言设置管理
-
资源管理器
- 数据库连接池(控制连接数)
- 打印任务队列(避免资源竞争)
-
状态管理
- Redux/Vuex的Store实例
- 用户登录会话管理
-
工具服务
- 日志记录器(统一输出格式)
- 性能监控服务(数据聚合)
代码实现(线程安全增强版)
class DatabaseConnection {constructor(config) {if (DatabaseConnection.instance) {return DatabaseConnection.instance}// 初始化数据库连接this.connection = this.createConnection(config)DatabaseConnection.instance = this}// 私有方法(实际项目应使用Symbol实现)createConnection(config) {console.log('Creating new database connection...')return { host: config.host,query: (sql) => console.log(`Executing: ${sql}`)}}// 静态访问器static getInstance(config) {if (!this.instance) {this.instance = new DatabaseConnection(config)}return this.instance}
}// 使用示例
const config = { host: 'localhost:3306' }
const db1 = DatabaseConnection.getInstance(config)
const db2 = DatabaseConnection.getInstance(config)console.log(db1 === db2) // true
db1.connection.query('SELECT * FROM users') // Executing: SELECT * FROM users
实现流程图解
注意事项
-
多线程环境
- 浏览器中通过Web Workers实现多线程时需加锁(如
Mutex
)
// 伪代码示例 if (navigator.locks) {navigator.locks.request('singleton_lock', async () => {return DatabaseConnection.getInstance()}) }
- 浏览器中通过Web Workers实现多线程时需加锁(如
-
测试困难
- 单例状态会跨测试用例保留,解决方案:
beforeEach(() => {DatabaseConnection.instance = null })
-
违反单一职责原则
- 同时承担实例创建和业务逻辑,可通过代理模式拆分:
class DatabaseSingleton {// 仅负责实例管理 }class DatabaseService {// 处理具体业务逻辑 }
现代框架中的演进
-
React Context API
// 创建单例上下文 const AuthContext = React.createContext(null)// 全局访问点 function useAuth() {return useContext(AuthContext) }
-
Vue3的provide/inject
// 创建单例服务 const storageService = reactive(new StorageService())// 注入全局 app.provide('storage', storageService)
模式延伸:单例模式常与工厂模式结合使用,形成多例模式(Multiton),通过键值对管理多个受限实例:
class LoggerMultiton {static instances = new Map()static getInstance(namespace) {if (!this.instances.has(namespace)) {this.instances.set(namespace, new Logger(namespace))}return this.instances.get(namespace)}
}
实现
// 现代ES6实现(线程安全版)
class Logger {constructor() {if (!Logger.instance) {this.logs = [];Logger.instance = this;}return Logger.instance;}log(message) {this.logs.push(message);console.log(`[LOG]: ${message}`);}
}// 使用示例
const logger1 = new Logger();
const logger2 = new Logger();
console.log(logger1 === logger2); // true
应用场景
- 全局状态管理(Redux Store)
- 浏览器环境对象(Window/Document)
- 日志记录器
2.2 观察者模式(Observer)
观察者模式(Observer Pattern)是行为型设计模式的经典实现,其核心目标是建立对象间的一对多依赖关系,当一个对象(被观察者)状态变化时,所有依赖它的对象(观察者)都会自动收到通知。以下是其关键要点:
核心特性
特性 | 说明 |
---|---|
松耦合 | 观察者与被观察者之间通过接口交互,无需了解彼此具体实现 |
动态订阅 | 允许运行时动态添加/移除观察者 |
广播通知 | 状态变化时自动通知所有已注册的观察者 |
推拉模型 | 支持推送完整数据或由观察者主动拉取数据(默认推模式) |
应用场景
-
事件驱动系统
- GUI组件交互(如按钮点击事件)
- 表单输入实时校验
-
实时数据同步
- 股票行情实时更新
- 多端数据同步(如协同编辑)
-
状态管理
- Vue响应式系统(基于Watcher)
- Redux中间件监听
-
异步任务协调
- 文件上传进度通知
- 批量数据处理状态跟踪
代码实现(支持防抖的增强版)
class Subject {constructor() {this.observers = new Set()this.state = nullthis.debounceTimer = null}// 注册观察者(支持自动去重)subscribe(observer, options = { debounce: 0 }) {const wrapper = data => {if (options.debounce > 0) {clearTimeout(this.debounceTimer)this.debounceTimer = setTimeout(() => observer.update(data), options.debounce)} else {observer.update(data)}}this.observers.add({ original: observer,wrapper})}// 移除观察者unsubscribe(observer) {for (const entry of this.observers) {if (entry.original === observer) {this.observers.delete(entry)break}}}// 状态更新(支持部分更新)setState(newState) {const prevState = this.statethis.state = { ...this.state, ...(typeof newState === 'function' ? newState(prevState) : newState)}this.notify()}// 通知所有观察者notify() {this.observers.forEach(({ wrapper }) => wrapper(this.state))}
}// 观察者基类
class Observer {update(data) {throw new Error('必须实现update方法')}
}// 使用示例
class Logger extends Observer {update(data) {console.log('[Logger]', data)}
}class Analytics extends Observer {update(data) {fetch('/api/analytics', {method: 'POST',body: JSON.stringify(data)})}
}// 初始化主题
const userSubject = new Subject()// 注册观察者(Logger立即响应,Analytics防抖500ms)
userSubject.subscribe(new Logger())
userSubject.subscribe(new Analytics(), { debounce: 500 })// 触发状态更新
userSubject.setState({ name: 'Alice' })
userSubject.setState({ age: 30 }) // Analytics只会收到最终合并状态
实现流程图解
注意事项
-
内存泄漏
- 未及时取消订阅会导致观察者无法回收,解决方案:
// 使用WeakMap存储弱引用 const observers = new WeakMap()// 或使用AbortController(浏览器环境) const controller = new AbortController() subject.subscribe(observer, { signal: controller.signal }) controller.abort() // 自动取消订阅
-
通知顺序
- 观察者执行顺序不可控,关键业务需顺序保证:
notify() {Array.from(this.observers).sort((a,b) => a.priority - b.priority).forEach(observer => observer.update()) }
-
性能问题
- 高频更新场景建议合并通知:
class BatchedSubject extends Subject {notify() {if (!this.pending) {this.pending = truerequestAnimationFrame(() => {super.notify()this.pending = false})}} }
现代框架中的演进
-
RxJS Observable
// 创建可观察对象 const source = rxjs.fromEvent(document, 'click')// 订阅观察者 const subscription = source.subscribe(e => console.log(e))// 取消订阅 subscription.unsubscribe()
-
Vue3的watchEffect
const state = reactive({ count: 0 })// 自动依赖追踪 const stop = watchEffect(() => {console.log('count:', state.count) })// 停止观察 stop()
-
React useEffect
useEffect(() => {const subscription = dataStream.subscribe(handleData)return () => subscription.unsubscribe() }, [])
模式延伸:观察者模式与发布-订阅模式的核心差异:
混合模式实践:结合代理模式实现安全观察:
class ProtectedSubject extends Subject {subscribe(observer) {const proxy = new Proxy(observer, {get(target, prop) {if (prop === 'update') {return (...args) => {try {target[prop](...args)} catch (e) {console.error('Observer error:', e)}}}return target[prop]}})super.subscribe(proxy)}
}
2.3 策略模式(Strategy)
策略模式(Strategy Pattern)是行为型设计模式的典型实现,其核心思想是定义一系列算法簇,使其可以相互替换,让算法的变化独立于使用它的客户端。以下是其关键要点:
核心特性
特性 | 说明 |
---|---|
算法封装 | 每个策略类封装独立算法实现 |
动态切换 | 运行时可根据需求自由切换不同策略 |
消除条件分支 | 避免多重if-else或switch-case语句 |
开闭原则 | 新增策略无需修改已有代码 |
应用场景
-
业务规则引擎
- 电商促销策略(满减、折扣、赠品)
- 运费计算规则(按重量、体积、地区)
-
数据处理管道
- 数据加密算法(AES、RSA、DES)
- 图片压缩策略(WebP、JPEG、PNG)
-
游戏开发
- 角色AI行为(攻击、防御、逃跑)
- 物理碰撞检测(AABB、OBB、球体检测)
-
表单验证系统
- 校验规则组合(必填、邮箱格式、长度限制)
- 多国手机号验证策略
代码实现(支持策略链的增强版)
// 策略接口定义
class ValidationStrategy {validate(value) {throw new Error('必须实现validate方法')}
}// 具体策略实现
class RequiredStrategy extends ValidationStrategy {validate(value) {return !!value.trim()}
}class EmailStrategy extends ValidationStrategy {validate(value) {return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)}
}class MinLengthStrategy extends ValidationStrategy {constructor(min) {super()this.min = min}validate(value) {return value.length >= this.min}
}// 策略上下文
class Validator {constructor() {this.strategies = []this.errors = []}addStrategy(strategy) {if (!(strategy instanceof ValidationStrategy)) {throw new Error('无效的策略类型')}this.strategies.push(strategy)return this // 支持链式调用}validate(value) {this.errors = this.strategies.map(strategy => strategy.validate(value) ? null : strategy.constructor.name).filter(Boolean)return {isValid: this.errors.length === 0,errors: this.errors}}
}// 使用示例
const userValidator = new Validator().addStrategy(new RequiredStrategy()).addStrategy(new MinLengthStrategy(6))const emailValidator = new Validator().addStrategy(new RequiredStrategy()).addStrategy(new EmailStrategy())console.log(userValidator.validate('Alice')) // { isValid: false, errors: ['MinLengthStrategy'] }
console.log(emailValidator.validate('test@')) // { isValid: false, errors: ['EmailStrategy'] }
实现流程图解
注意事项
-
策略膨胀问题
- 当策略超过10个时建议使用策略工厂:
class StrategyFactory {static create(type, ...args) {const strategies = {required: RequiredStrategy,email: EmailStrategy,minLength: MinLengthStrategy}return new strategies[type](...args)} }
-
策略共享状态
- 需要跨策略共享数据时使用上下文注入:
class AdvancedStrategy extends ValidationStrategy {constructor(context) {super()this.context = context} }
-
性能考量
- 高频调用场景建议缓存策略实例:
const strategyCache = new Map()function getStrategy(type) {if (!strategyCache.has(type)) {strategyCache.set(type, new strategies[type]())}return strategyCache.get(type) }
现代框架中的演进
-
React Hooks策略封装
function useValidation(strategyType) {const [error, setError] = useState(null)const validate = useCallback((value) => {const strategy = StrategyFactory.create(strategyType)const isValid = strategy.validate(value)setError(isValid ? null : 'Invalid value')return isValid}, [strategyType])return { validate, error } }
-
Vue3组合式API实现
export function usePaymentStrategy(strategyType) {const strategies = {alipay: () => ({ pay: (amount) => /* 支付宝逻辑 */ }),wechat: () => ({ pay: (amount) => /* 微信支付逻辑 */ })}return reactive(strategies[strategyType]()) }
-
Node.js中间件策略
const compressionStrategies = {gzip: require('compression'),brotli: require('compression/brotli') }app.use((req, res, next) => {const strategy = req.acceptsEncodings(['br', 'gzip'])return compressionStrategies[strategy]?.(req, res, next) || next() })
混合模式实践:策略模式+责任链实现复杂校验:
class ValidationChain {constructor() {this.strategies = []}add(strategy) {this.strategies.push(strategy)return this}validate(value) {return this.strategies.reduce((result, strategy) => {if (!result.isValid) return resultconst isValid = strategy.validate(value)return {isValid,failedStrategy: isValid ? null : strategy.constructor.name}}, { isValid: true })}
}
最佳实践原则:
- 策略粒度控制:单个策略应聚焦单一职责
- 无状态设计:优先使用纯函数策略实现
- 配置化策略:通过JSON配置动态加载策略
- 防御式编程:处理未知策略类型的降级方案
2.4 发布-订阅模式(Pub/Sub)
发布-订阅模式(Publish-Subscribe Pattern)是行为型设计模式的进阶实现,其核心思想是通过事件通道解耦消息发布者与订阅者,实现跨组件/跨系统的异步通信。以下是其关键要点:
核心特性
特性 | 说明 |
---|---|
完全解耦 | 发布者与订阅者互不感知,仅通过事件标识通信 |
异步通信 | 支持非阻塞式消息传递(基于事件循环) |
多对多关系 | 单个事件可被多个订阅者消费,单个订阅者可监听多个事件 |
消息持久化 | 可选实现消息队列持久存储(如RabbitMQ、Kafka) |
应用场景
-
分布式系统
- 微服务间通信(订单服务 → 库存服务)
- 实时数据分析管道
-
前端架构
- 微前端应用通信(qiankun框架)
- 组件间跨层级通信(非父子组件)
-
业务中台
- 用户行为追踪系统(埋点数据收集)
- 全站通知系统(公告/站内信广播)
-
物联网场景
- 设备状态监控(传感器数据分发)
- 智能家居联动(门锁开启 → 灯光调整)
代码实现(支持通配符的增强版)
class EventBus { constructor() { this.channels = new Map(); this.wildcardChannels = new Map(); // 存储通配符订阅 } // 支持 event.* 格式的通配符 subscribe(event, callback) { if (event.includes('*')) { const base = event.replace(/\*/, ''); const listeners = this.wildcardChannels.get(base) || new Set(); listeners.add(callback); this.wildcardChannels.set(base, listeners); } else { const listeners = this.channels.get(event) || new Set(); listeners.add(callback); this.channels.set(event, listeners); } } // 支持一次性订阅 once(event, callback) { const wrapper = (...args) => { callback(...args); this.unsubscribe(event, wrapper); }; this.subscribe(event, wrapper); } unsubscribe(event, callback) { if (event.includes('*')) { const base = event.replace(/\*/, ''); const listeners = this.wildcardChannels.get(base); if (listeners) listeners.delete(callback); } else { const listeners = this.channels.get(event); if (listeners) listeners.delete(callback); } } publish(event, data) { // 精确匹配 this.channels.get(event)?.forEach(cb => cb(data)); // 通配符匹配 const [namespace] = event.split('.'); this.wildcardChannels.get(namespace + '.')?.forEach(cb => cb(data)); }
} // 使用示例
const bus = new EventBus(); // 订阅精确事件
bus.subscribe('order.created', (order) => { console.log('处理新订单:', order);
}); // 订阅通配符事件
bus.subscribe('order.*', (event) => { console.log('订单状态变更:', event.type);
}); // 一次性订阅
bus.once('user.login', (user) => { console.log('欢迎首次登录:', user.name);
}); // 发布事件
bus.publish('order.created', { id: 1, total: 100 });
bus.publish('order.updated', { id: 1, status: 'shipped' });
实现流程图解
注意事项
-
内存泄漏防护
- 使用
WeakRef
+FinalizationRegistry
自动清理:
const registry = new FinalizationRegistry(({ event, wrapper }) => { eventBus.unsubscribe(event, wrapper); }); function safeSubscribe(event, callback) { const ref = new WeakRef(callback); const wrapper = (data) => ref.deref()?.(data); registry.register(callback, { event, wrapper }); eventBus.subscribe(event, wrapper); }
- 使用
-
消息顺序保障
- 添加优先级队列:
class PriorityEventBus extends EventBus { subscribe(event, callback, priority = 0) { super.subscribe(event, { callback, priority }); // 按priority排序存储 } }
-
错误隔离机制
- 防止单个订阅者崩溃影响全局:
publish(event, data) { this.channels.get(event)?.forEach(cb => { try { cb(data); } catch (e) { console.error('事件处理异常:', e); } }); }
现代框架中的演进
-
Vue3的provide/inject事件总线
// 创建Symbol标识的事件类型 const ORDER_EVENT = Symbol('order'); // 提供事件发射器 provide(ORDER_EVENT, { emit: (type, data) => bus.publish(`order.${type}`, data), on: (type, callback) => bus.subscribe(`order.${type}`, callback) }); // 注入使用 const { emit, on } = inject(ORDER_EVENT);
-
React的useSyncExternalStore
function useEventStore(event) { const [data, setData] = useState(null); useEffect(() => { const handler = (payload) => setData(payload); bus.subscribe(event, handler); return () => bus.unsubscribe(event, handler); }, [event]); return data; }
-
Node.js的EventEmitter
const { EventEmitter } = require('events'); const emitter = new EventEmitter(); // 异步监听处理 emitter.on('log', async (message) => { await writeToFile(message); }); // 错误处理 emitter.on('error', (err) => { console.error('Event Error:', err); });
模式延伸
-
与中介者模式结合
-
领域事件设计
class DomainEvent { constructor(type, payload) { this.id = uuidv4(); this.timestamp = Date.now(); this.type = type; this.payload = Object.freeze(payload); } } // 发布领域事件 bus.publish('domain', new DomainEvent('OrderPaid', { orderId: 123 }));
-
消息回溯实现
class ReplayEventBus extends EventBus { constructor() { super(); this.history = new Map(); } publish(event, data) { super.publish(event, data); const records = this.history.get(event) || []; records.push({ timestamp: Date.now(), data }); this.history.set(event, records.slice(-100)); // 保留最近100条 } replay(event, callback) { this.history.get(event)?.forEach(record => callback(record.data)); } }
架构级应用:在微前端场景下的跨应用通信方案
// 主应用注册全局总线
window.globalEventBus = new EventBus(); // 子应用A发布事件
window.globalEventBus.publish('cart/update', { count: 5 }); // 子应用B订阅事件
window.globalEventBus.subscribe('cart/update', (payload) => { document.getElementById('cart-counter').textContent = payload.count;
});
三、设计模式黄金法则
- 不滥用原则:避免过度设计(YAGNI原则)
- 场景适配:根据业务复杂度选择模式
- 模式组合:多数场景需要多模式配合
- 模式演进:现代框架已内置模式实现
四、下期预告
总共有23种经典的设计模式,本篇文章介绍了4种前端开发中常用的设计模式,其他设计模式将在下篇文章中继续分享哦,敬请期待~
相关文章:
深入浅出JavaScript常见设计模式:从原理到实战(1)
深入浅出JavaScript常见设计模式:从原理到实战(1) 设计模式是一种在特定情境下解决软件设计中常见问题的通用方案或模板。在特定的开发场景中使用特定的设计模式,可以提升代码质量,增强代码可读性和可维护性,提高团队开发效率&…...
RCE学习
一、远程代码执行漏洞 1. 远程代码执行的定义 定义:远程代码执行漏洞(Remote Code Execute,简称RCE)是指程序预留了执行命令或代码的接口并被黑客利用的漏洞。广义上也包括远程命令执行(Remote Command Execute&…...
Redis安装及入门应用
应用资料:https://download.csdn.net/download/ly1h1/90685065 1.获取文件,并在该文件下执行cmd 2.输入redis-server-lucifer.exe redis.windows.conf,即可运行redis 3.安装redis客户端软件 4.安装后运行客户端软件,输入链接地址…...
【棒球运动】户外运动安全技巧·棒球1号位
以棒球运动为例,在棒球这项结合力量、速度与策略的户外运动中,安全防护是保障运动表现的核心。以下是针对棒球特点的户外安全指南,涵盖装备、环境与行为规范三大维度: 一、场景化防护装备选择 击球场景 击球手需佩戴双重防护头盔…...
卸载rpm包
昨天了解了查询rpm包的流程和命令,那么今天了解一下删除rpm包的语法,那么话不多说,来看. 1.基本语法 rpm -e RPM包的名称 注:e erase擦除 2.案例 删除firefox软件包 :rpm -e firefox 3.细节讨论 1.如果其它软件包依赖于要卸载的软件包,卸载时…...
【AI提示词】艺人顾问
提示说明 专业艺人顾问,专注于为客户提供全面的艺术、娱乐和商业咨询服务,帮助他们在竞争激烈的行业中树立品牌影响力,提升市场竞争力 提示词 # Role: 艺人顾问## Profile - language: 中文 - description: 专业艺人顾问,专注于…...
第七部分:向量数据库和索引策略
什么是矢量数据库? 简单来说,向量数据库是一种专门化的数据库,旨在优化存储和检索以高维向量形式表示的文本。 为什么这些数据库对RAG至关重要?因为向量表示能够在大规模文档库中进行高效的基于相似性的搜索,根据用户…...
26考研|数学分析:数项级数
数项级数这一章的开始,开启了新的关于“级数”这一新的概念体系的学习进程,此部分共包含四章的内容,分别为数项级数、函数项级数、幂级数以及傅里叶级数。这一章中,首先要掌握级数的相关概念与定义,重难点在于掌握判断…...
2025 年免费 Word 转 PDF 转换器有哪些?
我们列出了最好的 Word 到 PDF 转换器,以便轻松轻松地将 .doc 文件导出到 .pdf 而不会丢失原始格式。 尽管 Microsoft 365 包含一个 Word 版本,该版本可以将您正在处理的 .docx 文档无缝导出为 PDF 格式,但仍在使用旧版 Word 的人可能缺少此…...
【Spring Boot】深入解析:#{} 和 ${}
1.#{} 和 ${}的使用 1.1数据准备 1.1.1.MySQL数据准备 (1)创建数据库: CREATE DATABASE mybatis_study DEFAULT CHARACTER SET utf8mb4;(2)使用数据库 -- 使⽤数据数据 USE mybatis_study;(3ÿ…...
SpringMVC知识体系
SpringMVC 知识体系 1. SpringMVC 基础 MVC 设计模式 Model: 模型层,处理业务逻辑View: 视图层,负责界面展示Controller: 控制层,处理请求并协调模型和视图 核心组件 DispatcherServlet: 前端控制器HandlerMapping: 处理器映射Controller: …...
如何将 PDF 中的文本提取为 JSON 格式
一些 PDF 文件是“带标签”的,意味着它们包含关于文件结构的信息。这种结构作为元数据嵌入在 PDF 中,由一系列标签组成,用于标记诸如标题、段落、列表、表格和图像等元素。 这非常类似于 HTML,其中的文本包含在具有语义意义的元素…...
深度解析:基于Python的微信小程序自动化操作实现
引言 在当今数字化时代,自动化技术正在改变我们与软件交互的方式。本文将深入解析一个使用Python实现的微信小程序自动化操作脚本,该脚本能够自动识别屏幕上的特定图像并执行点击操作。这种技术在自动化测试、批量操作和效率工具开发中有着广泛的应用前…...
【网络安全】网络钓鱼的类型
1. 网络钓鱼简介 网络钓鱼是最常见的社会工程学类型之一,它是一种利用人为错误来获取私人信息、访问权限或贵重物品的操纵技术。之前,您学习了网络钓鱼是如何利用数字通信诱骗人们泄露敏感数据或部署恶意软件的。 有时,网络钓鱼攻击会伪装成…...
Python----深度学习(基于深度学习Pytroch线性回归和曲线回归)
一、引言 在当今数据驱动的时代,深度学习已成为解决复杂问题的有力工具。它广泛应用于图像识别、自然语言处理和预测分析等领域。回归分析是统计学的一种基础方法,用于描述变量之间的关系。通过回归模型,我们可以预测连续的数值输出…...
重构智能场景:艾博连携手智谱,共拓智能座舱AI应用新范式
2025年4月24日,智能座舱领域创新企业艾博连科技与国产大模型独角兽智谱,在上海国际车展艾博连会客厅签署合作协议。双方宣布将深度整合智谱在AI大模型领域的技术积淀与艾博连在汽车智能座舱场景的落地经验,共同推进下一代"有温度、懂需求…...
Streamlit从入门到精通:构建数据应用的利器
在数据科学与机器学习日益普及的今天,如何快速将模型部署为可交互的应用成为了许多数据科学家的重要任务。Streamlit,作为一个开源的Python库,专为数据科学家设计,能够帮助我们轻松构建美观且直观的Web应用。本文将从入门到精通&a…...
4.1.1 类的序列化与反序列化(XmlSerializer)
本文介绍XML序列化和反序列化操作 本例子中被序列化的类(Devices)中有一个List,其元素类型为:DigitalInputInfo. 序列化以及反序列化都很简单: 序列化:即把类的对象输出到文件中。 StreamWriter streamWriter new StreamWriter(filePath); …...
新增优惠券
文章目录 概要整体架构流程技术细节小结 概要 接口分析 一个基本的新增接口,按照Restful风格设计即可,关键是请求参数。之前表分析时已经详细介绍过这个页面及其中的字段,这里不再赘述。 需要特别注意的是,如果优惠券限定了使…...
Qt 处理 XML 数据
在 Qt 中,处理 XML 数据通常使用 Qt 提供的 QDomDocument、QXmlStreamReader 和 QXmlStreamWriter 类。这些类可以帮助你读取、修改和写入 XML 数据。 1. 使用 QDomDocument 处理 XML QDomDocument 提供了对 XML 文档的 DOM(Document Object Model&…...
STM32F407使用ESP8266实现阿里云OTA(下)
文章目录 前言一、函数分析1.get_bin()函数2.download_bin()函数3.串口1中断函数二、完整工程分析前言 从上一章中,我们已经成功连接阿里云并且成功拿到了升级包的下载地址,在本文我们将升级包下载下来并且存储到SD卡中,最终将程序写入FLASH中完成APP的跳转,至此我们的OTA…...
树型结构(知识点梳理及例题精讲)
大家好啊,这一集,我们来学习树型结构,请确保看完预习篇,再来看此篇哦 树型结构(预习课)-CSDN博客 话不多说,直接开讲 -------------------------------------------------------分割线-------…...
使用HYPRE库并行装配IJ稀疏矩阵指南: 矩阵预分配和重复利用
使用HYPRE库并行装配IJ稀疏矩阵指南 HYPRE是一个流行的并行求解器库,特别适合大规模稀疏线性系统的求解。下面介绍如何并行装配IJ格式的稀疏矩阵,包括预先分配矩阵空间和循环使用。 1. 初始化矩阵 首先需要创建并初始化一个IJ矩阵: #incl…...
win11什么都不动之后一段时间黑屏桌面无法显示,但鼠标仍可移动,得要熄屏之后才能进入的四种解决方法
现象: 1. 当时新建运行的资源管理器的任务卡了或者原本资源管理器卡了 比如:当时在文本框中输入explorer 注:explorer.exe是Windows的文件资源管理器,它用于管理Windows的图形外壳,包括桌面和文件管理 按住CtrlAltEs…...
C语言编程--15.四数之和
题目: 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复)&…...
从单机工具到协同平台:开源交互式模拟环境的技术演进之路
从单机工具到协同平台:开源交互式模拟环境的技术演进之路 一、引言:从“孤岛”到“生态”的模拟技术变革 二十年前,模拟软件如LAMMPS(分子动力学)、ANSYS(工程仿真)以单机版为主,用…...
Python函数与模块笔记
Python函数与模块笔记 目录 函数 无参函数带参函数变量作用域Lambda函数常用内置函数 模块与包 模块的定义与导入包的使用常用模块(keyword、random、sys、time) 一、函数 1. 无参函数 定义语法: def 函数名(): 代码块 return [表达式]…...
Jenkins:开启高效软件开发的魔法之门
一、Jenkins 是什么 Jenkins 是一款基于 Java 开发的开源持续集成工具,在软件开发流程中占据着举足轻重的地位。它的前身是 Hudson ,于 2004 年由 Sun 公司的 Kohsuke Kawaguchi 开发,2011 年因商标纠纷更名为 Jenkins。发展至今,…...
正则表达式学习指南
正则表达式学习指南 在编程的世界里,正则表达式(Regular Expressions,简称regex)是一门不可或缺的艺术,它赋予了开发者强大的文本处理能力,让看似复杂的字符串匹配和替换任务变得简单而高效。本文旨在为初…...
React-组件通信
1、父子组件通信 (1)父传子(props 传值) // 父组件 function App() {const name 张三return (<div className"App"><Son name{name} /></div>); }// 子组件 function Son(props) {return (<div…...
MuJoCo 机械臂 PPO 强化学习逆向运动学(IK)
视频讲解: MuJoCo 机械臂 PPO 强化学习逆向运动学(IK) 代码仓库:https://github.com/LitchiCheng/mujoco-learning 结合上期视频,我们安装了stable_baselines3和gym,今天用PPO尝试强化学习得到关节空间到达…...
代码随想录算法训练营第一天:数组part1
今日学习的文章链接和视频链接 ● 自己看到题目的第一想法 ● 看完代码随想录之后的想法 ● 自己实现过程中遇到哪些困难 ● 今日收获,记录一下自己的学习时长 状态 思路理解完成 30% 代码debug完成 60% 代码模板总结并抽象出来 100% 题目 704 二分查找 题目链接…...
C++学习:六个月从基础到就业——STL算法(二)排序与变序算法
C学习:六个月从基础到就业——STL算法(二)排序与变序算法 本文是我C学习之旅系列的第二十六篇技术文章,也是第二阶段"C进阶特性"的第四篇,主要介绍C STL算法库中的排序和变序算法。查看完整系列目录了解更多…...
JVM性能优化之年轻代参数设置
一、引言 在Java应用开发中,性能问题往往是最难预测却又最影响用户体验的关键因素。即便代码逻辑完美,若JVM(Java虚拟机)配置不当,也可能导致频繁GC停顿、内存泄漏,甚至引发系统崩溃。JVM性能优化并非简单…...
A*迷宫寻路
二、实验内容 以寻路问题为例实现A*算法的求解程序,设计两种不同的估价函数: 1.设置两种地图: 根据题意,用矩阵设置两个地图。 地图1:设置5行5列的迷宫,代码如下: 地图2:设置20行…...
秒出PPT推出更强版本,AI PPT工具进入新纪元!
在现代职场中,PPT是我们沟通和展示信息的重要工具。无论是做产品演示,还是准备工作汇报,一份精美的PPT能大大提升演示效果。然而,传统的PPT制作往往需要消耗大量时间,尤其是在排版、设计和内容调整上。如今,…...
electron-updater实现自动更新
electron-updater 是一个专为 Electron 应用设计的自动更新工具,能够帮助开发者轻松实现跨平台的自动更新功能。它支持 Windows、macOS 和 Linux 系统,通过简单的配置即可集成到 Electron 应用中,自动检查应用的最新版本并在后台完成更新。el…...
Ubuntu22学习记录
Ubuntu22学习记录 虚拟机挂载共享文件夹离线安装.net core3.1离线安装mysql离线安装supervisor离线安装nginx开机自启 虚拟机挂载共享文件夹 sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other 挂载路径:/mnt/hgfs/离线安装.net core3.1 离线安装mysql 离线安装…...
【MinerU】:一款将PDF转化为机器可读格式的工具——RAG加强(Docker版本)
目录 创建容器 安装miniconda 安装mineru CPU运行 GPU加速 多卡问题 创建容器 构建Dockerfile文件 开启ssh服务,设置密码为1234等操作 # 使用官方 Ubuntu 24.04 镜像 FROM ubuntu:24.04# 安装基础工具和SSH服务 RUN apt-get update && \apt-get ins…...
leetcode 69和367
69. Sqrt(x) 代码: class Solution { public:int mySqrt(int x) {int left 0;int right x;long long mid 0;int res 0;long long temp 0;while(left < right){mid left ((right - left)>>1);temp mid*mid;if(temp x){res mid;break;}else if(te…...
# 代码随想录算法训练营Day37 | Leetcode300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组
代码随想录算法训练营Day37 | Leetcode300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组 一、最长递增子序列 相关题目:Leetcode300 文档讲解:Leetcode300 视频讲解:Leetcode300 1. Leetcode300.最长递增子序列 给你一个整数数…...
中小企业技术跃迁:云原生后端如何实现高效低成本系统建设
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:技术变革的“门槛”能否被跨越? 过去十年,云计算与容器化技术飞速发展,互联网巨头纷纷构建自己的云原生基础设施,实现系统模块化、弹性伸缩、自动化运维。然而,中小企业在这股浪潮中…...
系统架构师2025年论文《系统架构风格2》
论软件系统架构风格 摘要: 某市医院预约挂号系统建设推广应用项目是我市卫生健康委员会 2019 年发起的一项医疗卫生行业信息化项目,目的是实现辖区内患者在辖区各公立医疗机构就诊时,可以通过多种线上渠道进行预约挂号。我作为系统架构师参与此项目。本文围绕软件系统架构…...
Java面试实战:电商场景下的Spring Cloud微服务架构与缓存技术剖析
第一轮提问 面试官: 谢飞机,我们先从基础问题开始。请问你知道Spring Boot和Spring Cloud的区别吗? 谢飞机: 当然知道!Spring Boot主要用于快速构建独立运行的Spring应用,而Spring Cloud则是在Spring Boot的基础上实现分布式系统…...
快速配置linux远程开发-go语言
1.go安装包安装 2.go env 配置 go env -w GO111MODULEon go env -w GOPROXYxx go env -w GOSUMDBoff go env -w GOPRIVATExx 3.复制linux公钥到gitlab中,用于通过ssh免密拉取gitlab项目 ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 4.设置…...
C++23文本编码革新:迈向更现代的字符处理
文章目录 一、字符集与编码(P2314R4)二、统一的字符字面量编码(P2316R2)三、具名通用字符转义(P2071R2)四、带分隔的转义序列(P2290R3)五、支持UTF-8作为可移植源文件编码࿰…...
CentOS系统中MySQL安装步骤分享
在 CentOS 系统上安装 MySQL,需要依次进行环境检查、软件源配置、安装 MySQL、启动服务等操作。我将按照规范流程,为你详细分享完整且具体的安装步骤。 在 CentOS 系统中安装 MySQL 数据库,能够为各类应用提供高效稳定的数据存储和管理服务。…...
【产品经理从0到1】Axure介绍
01. 上期内容回顾 创建元件库的时候,在添加原件时不知道怎么操作。讲解很耐心,希望课上分解步骤多带着练习下;PC 端的原型,相对于移动端,非常自由,没有任何的设计规范;但是,要求 PC…...
30天通过软考高项-第二天
30天通过软考高项-第二天 任务:项目立项管理、项目整合管理 思维导图阅读 知识点记忆 章节习题练习 知识点练习 手写回忆ITTO 立项管理-背 1. 项目可研的5个方面 基金社运法 技术可行性、经济可行性、社会效益可行性、运行环境可行性、其他(法律、政…...
yt-dlp 下载时需要 cookie
下载 b 站 歌曲 yt-dlp -x --proxy http://127.0.0.1:1080 --audio-format mp3 https://www.bilibili.com/video/BV1Zn4y1X75b解决方案,使用 firefox 登录相关网站 yt-dlp -o "downloads/%(title)s.%(ext)s" -f "bestvideo[height<1080]bestaud…...