简介本资源是一份面向软件开发初学者与中级工程师的《软件设计模式——原型模式》教学PPT系统讲解创建型设计模式中的核心实践方法。内容覆盖原型模式定义、浅拷贝与深拷贝原理对比、Java中Cloneable接口与clone()方法实现细节、三大角色抽象原型类、具体原型类、客户类职责划分以及典型使用场景如高成本对象创建、状态定制化副本生成和优缺点分析。PPT结构清晰含概述、应用场景、克隆机制详解、完整可运行代码示例及关键注意事项便于课堂讲授或自学理解。资源为1个5.93MB的pptx文件格式规范、图文并茂、代码高亮适合作为教学课件或复习提纲。目前已有193人学习下载是掌握原型模式底层机制与工程落地要点的实用入门材料。1. 原型模式到底是什么就像复印身份证不是重新办一张你有没有过这种经历去银行办业务柜员让你填三份一模一样的表格——姓名、身份证号、手机号、地址……全都要重复写。你一边写一边想这不就是把第一份复印两份完事了吗何必从头再打一遍原型模式就是编程世界里的“复印机”。它不靠 new 关键字从零造对象像重新跑一次身份证申领流程而是拿一个现成的、已经配好所有字段的“样板对象”比如一封写好的邮件、一个初始化完毕的配置实例按个“复制”键瞬间生成一个一模一样的新对象。这个“样板”就叫原型Prototype这个“按键复制”的动作就叫克隆Clone。为什么值得搞懂因为很多真实场景里“造对象”根本不是点一下鼠标那么简单它可能要读五次数据库、调三次外部接口、解析两份 XML 配置、再校验七条业务规则——整个过程耗时几百毫秒。而如果你只需要微调其中一两个字段比如把收件人从“张三”改成“李四”却硬要走完整套初始化流程就像为了改个邮箱后缀跑去公安局注销旧身份证、再重新申请一张——纯属自我消耗。原型模式就是帮你绕开这套“重走长征路”的笨办法用内存级的拷贝把“高频、轻量、定制化”的对象创建变得像 CtrlC / CtrlV 一样丝滑。它不是炫技而是对“重复劳动”的一次精准外科手术。2. 为什么需要原型模式当 new 太慢、太重、太僵硬的时候2.1 new 的三大硬伤慢、重、僵我们先直面现实new SomeClass()这行代码表面看只是敲了几个字母背后却可能藏着一场小型灾难。慢想象一个ReportGenerator类它的构造函数里要加载 20MB 的模板文件、连接报表服务器、预热缓存、校验用户权限……每次new ReportGenerator()都得重跑一遍。如果系统每秒要生成 50 份不同用户的报表光初始化就吃掉 2 秒 CPU 时间——用户还没看到报表服务器先喘不过气。重有些对象天生“胖”。比如一个GameWorld实例内部持有地形网格、NPC 状态树、天气系统、物理引擎引用……这些资源要么占内存大要么初始化依赖外部服务。频繁 new等于在内存里堆起一座座小山GC垃圾回收会天天上门催债。僵new是编译期绑定的。你写死new UserAccount()就永远只能得到UserAccount想临时换成VIPUserAccount得改代码、重新编译、发版——可运营同学下午三点就要上线“VIP 试用活动”你凌晨两点还在改工厂类这就不是技术问题是协作灾难。原型模式怎么破它把“创建逻辑”从代码里抽出来变成对象自身的能力。你不再说“我要一个新对象”而是说“请给我一个和这个一模一样的副本”。样板对象原型自己知道怎么复制自己——它可能用clone()快速内存拷贝也可能用序列化深挖到底层甚至能动态决定哪些字段该保留、哪些该重置。客户端完全不用关心“怎么造”只管“要什么”。提示原型模式不是要取代new而是给new装上涡轮增压。简单对象、无状态工具类继续new干净利落。但凡涉及“初始化成本高”“结构复杂”“需动态变体”原型就是那个按需启动的备用引擎。2.2 它解决的其实是“对象复用”的终极命题软件设计里有个朴素真理能复用的绝不重建能共享的绝不复制能懒加载的绝不早初始化。原型模式就是这条真理在“对象创建”环节的具象化。举个具体例子某高校教务系统的“课程排班模块”。每学期初管理员要为 200 门课生成初始课表。每门课的课表对象Schedule包含教室ID、教师ID、周次范围、节次列表、班级列表、冲突检测规则……初始化一个Schedule平均要查 4 张数据库表、调 2 次校验服务、计算 3 分钟排班约束。如果用new Schedule()创建 200 次总耗时可能突破 10 分钟管理员得盯着进度条喝三杯咖啡。用原型模式怎么做先用new Schedule()创建一个“标准课表原型”比如默认排在周一第1-2节教室A101教师张老师调用它的clone()方法瞬间得到 200 个副本对每个副本只修改差异字段copy1.setCourse(高等数学)、copy2.setTeacher(李教授)、copy3.setRoom(B202)……整个过程从 10 分钟降到 2 秒内——因为 99% 的初始化工作只做了一次。这背后是思维转变从“面向过程式创建”一步步组装转向“面向结果式复用”先有成品再微调。它让对象从“一次性消耗品”变成了可无限分身的“数字分身”。2.3 不是所有对象都适合当原型三个硬性门槛原型模式虽好但绝非万能膏药。一个对象要想成为合格的“原型”必须跨过三道坎门槛为什么重要不达标会怎样可复制性原型必须能被安全、完整地拷贝。Java 中要求实现Cloneable接口并重写clone()其他语言需提供等效机制如 Python 的copy.deepcopy()。如果类没实现克隆调用clone()直接抛异常若克隆逻辑有 bug比如漏拷某个字段副本数据错乱后续所有操作都是空中楼阁。状态稳定性原型自身的状态在被克隆期间必须稳定。不能一边被复制一边被其他线程修改其字段。出现“半截克隆”副本里部分字段是旧值部分是新值对象处于不可预测的中间态调试时你会怀疑人生。依赖可迁移性原型若持有外部资源引用如数据库连接、文件句柄、网络 socket这些引用无法直接复制——副本拿到的还是同一个连接两个对象共用一个“水管”必然打架。克隆后对象看似独立实则共享底层资源。一个副本关闭连接另一个立刻报IOException一个副本写文件另一个读到脏数据。所以别急着给所有类加clone()。先问自己这个对象是不是“纯数据容器”它有没有外部依赖它的字段是否都支持浅拷贝或深拷贝答案是否定的就老老实实用new或工厂模式——强行套原型只会把简单问题复杂化。3. 浅克隆 vs 深克隆复印身份证复印件上的“住址”是手写还是打印3.1 一个邮件系统的血泪现场假设你在开发一个邮件客户端核心类Email长这样public class Email implements Cloneable { private String sender; // 发件人String值类型 private String subject; // 主题String值类型 private String body; // 正文String值类型 private Attachment attachment; // 附件引用类型指向另一个对象 }附件类Attachment很简单public class Attachment { private String fileName; private long fileSize; public void download() { /* 下载逻辑 */ } }现在你用原型模式创建一封邮件原型并克隆它Attachment originalAttachment new Attachment(); originalAttachment.fileName report.pdf; Email originalEmail new Email(mecompany.com, teamcompany.com, Q3报告, 详见附件, originalAttachment); Email clonedEmail originalEmail.clone(); // 浅克隆问题来了当你修改clonedEmail的附件时originalEmail会受影响吗答案取决于你用的是浅克隆还是深克隆——这就像复印身份证时复印件上的“住址”是直接印上去的深克隆还是你手写补上去的浅克隆。3.2 浅克隆只复制“指针”不复制“内容”浅克隆Shallow Cloning的逻辑非常直白对于基本类型int, boolean, String 等不可变对象直接复制值对于引用类型如Attachment只复制它在内存中的地址即“指针”不复制它指向的那个对象本身。用上面的邮件例子// 浅克隆后内存布局是这样的 // originalEmail.attachment ────────────────┐ // ├─→ 指向同一个 Attachment 对象 // clonedEmail.attachment ──────────────────┘所以如果你执行clonedEmail.getAttachment().fileName updated_report.pdf; // 修改副本的附件名 System.out.println(originalEmail.getAttachment().fileName); // 输出updated_report.pdf原邮件的附件名也变了因为两个Email对象的attachment字段指向内存中同一个Attachment实例。改一个等于改了俩。提示Java 的Object.clone()默认就是浅克隆。它快得飞起就是内存地址复制但危险得像走钢丝——你必须清楚知道哪些字段是引用类型哪些会被共享。3.3 深克隆连“纸”带“墨”一起复印彻底隔离深克隆Deep Cloning的目标只有一个让副本和原型从顶层对象到最底层嵌套对象完全独立互不干扰。它不仅要复制Email对象本身还要递归地复制它持有的Attachment甚至Attachment内部如果有其他引用比如FileMetadata也要一并复制。继续邮件例子深克隆后的内存布局originalEmail.attachment ──→ [Attachment A] (fileNamereport.pdf) clonedEmail.attachment ──→ [Attachment B] (fileNamereport.pdf, 独立内存空间)此时修改clonedEmail的附件对originalEmail绝对零影响clonedEmail.getAttachment().fileName final_report.pdf; System.out.println(originalEmail.getAttachment().fileName); // 仍是 report.pdf3.4 怎么选一张决策表说清本质区别特性浅克隆深克隆速度⚡ 极快O(1) 时间复杂度只复制地址 较慢O(n)n 是所有嵌套对象的总数量需递归遍历内存占用 小副本和原型共享大部分对象 大副本拥有自己的一整套对象树安全性⚠️ 低引用共享易引发意外修改✅ 高完全隔离副本修改不影响原型实现难度✅ 简单Java 中重写clone()即可❗ 复杂需手动处理每个引用字段或借助序列化等黑科技适用场景- 对象结构扁平引用类型极少- 共享引用是预期行为如全局配置对象- 对性能极度敏感且能严格控制引用不被修改- 对象有深层嵌套引用如邮件附件附件元数据- 副本需绝对独立避免任何副作用- 数据一致性要求极高如金融交易凭证记住一句口诀“浅克隆省时间深克隆保安全要快选浅要稳选深。”没有银弹只有权衡。4. 常见误区与易混概念别把原型模式当成“复制粘贴”或“继承”4.1 误区一原型模式 简单的new 手动赋值为什么混初学者看到“复制对象”第一反应是Email copy new Email(); copy.setSender(src.getSender()); copy.setSubject(src.getSubject()); ...觉得这不就是原型模式怎么区分这是手工克隆不是原型模式。原型模式的核心是对象自复制能力——src.clone()这一行代码背后封装了完整的复制逻辑包括处理引用、异常、深浅策略。手工赋值代码冗长易漏字段一旦Email新增字段所有手工克隆处都要补完全无法处理深克隆你得手动new Attachment()再赋值违背开闭原则——扩展性为零。原型模式把“怎么复制”交给对象自己客户端只管“我要副本”这才是解耦。4.2 误区二原型模式 Java 的clone()方法为什么混Java 文档里clone()是原型模式最常见实现很多人以为“用了clone()就是用了原型模式”。怎么区分clone()只是一个技术手段原型模式是一个设计思想。关键区别在于clone()是语言特性可能抛异常、需实现接口、默认浅克隆原型模式是架构决策它定义了Client使用者、Prototype抽象接口、ConcretePrototype具体实现三者关系强调“通过原型指定类型而非通过类名”。你可以不用clone()实现原型模式比如用 JSON 序列化/反序列化new ObjectMapper().readValue(json, Email.class)或者用构造函数传入另一个对象new Email(src)。只要满足“用现有实例创建新实例”的意图就是原型模式。4.3 误区三原型模式 继承Inheritance为什么混两者都涉及“基于已有东西创建新东西”名字听起来像亲戚。怎么区分继承是编译期静态关系子类VIPUser继承父类User获得其属性和方法但VIPUser和User是不同类型new VIPUser()创建的是VIPUser实例原型模式是运行期动态复制Email克隆出的还是Email类型完全相同只是内存地址不同。它解决的是“同类型对象的高效创建”而非“类型扩展”。混淆后果严重想用继承来避免new开销不行——继承不减少构造函数执行次数想用原型模式实现多态也不行——克隆出来的永远是原型的类型不会变成子类。4.4 误区四浅克隆一定不安全深克隆一定安全为什么混看到“浅克隆共享引用”就认为它“有毒”看到“深克隆完全隔离”就觉得它“完美”。怎么区分安全性取决于使用场景而非克隆方式本身。浅克隆可以很安全如果Attachment是不可变对象final字段无 setter那么共享引用毫无风险——谁也改不了它。深克隆可能很危险如果Attachment内部持有Socket连接深克隆时复制了 socket 句柄两个副本同时往同一个 socket 写数据网络层直接崩溃。真正该问的不是“用深还是浅”而是“这个引用对象允许多个所有者吗它的状态是否允许被并发修改” —— 答案决定了克隆策略。4.5 误区五原型模式只能用于 Java为什么混项目正文里全是 Java 代码和Cloneable接口让人误以为这是 Java 专属。怎么区分原型模式是通用设计思想与语言无关。Python 用copy.copy()浅和copy.deepcopy()深JavaScript 用展开运算符{...obj}浅或structuredClone()深现代浏览器Go 用结构体字面量或encoding/gob库。Java 的clone()只是其中一种实现路径切勿以偏概全。5. 什么时候用原型模式一个电商库存系统的实战判断5.1 场景还原秒杀活动前的库存快照风暴某电商平台准备双十一大促核心商品“旗舰手机”要开启万人秒杀。技术团队发现一个致命瓶颈每次用户点击“立即抢购”系统需生成一个OrderRequest对象包含用户ID、商品ID、SKU编码、期望价格、优惠券ID、风控令牌、时间戳……这个对象的初始化要查用户等级表、商品库存表、优惠券中心、风控服务平均耗时 80ms。预估峰值 QPS 5000意味着每秒要创建 5000 个OrderRequest仅初始化就吃掉 400 秒 CPU 时间——服务器直接雪崩。团队开了三次会否决了多个方案✖️缓存OrderRequest模板不行每个请求的用户ID、时间戳都不同缓存无效✖️异步创建不行下单链路必须同步返回结果否则用户看到“提交中…”转圈十分钟✖️简化字段不行风控令牌、优惠券ID 等字段业务强依赖砍不得。最后架构师拍板上原型模式。但不是盲目上而是做了三步严谨判断5.2 判断一对象是否满足原型三门槛门槛检查结果结论可复制性OrderRequest是纯 POJO无外部资源不连 DB、不持 socket所有字段都是基本类型或String/Long等不可变对象。✅可安全克隆状态稳定性秒杀开始前系统会预热一个“标准订单请求原型”之后只读不被修改。✅克隆过程无竞态依赖可迁移性所有字段均为值类型或不可变引用无共享风险。✅无需深克隆浅克隆足矣5.3 判断二克隆策略选浅还是深分析OrderRequest字段public class OrderRequest { private Long userId; // long值类型 → 浅克隆直接复制 private String skuCode; // String不可变 → 浅克隆安全 private BigDecimal price; // BigDecimal不可变 → 安全 private String couponId; // String不可变 → 安全 private String riskToken; // String不可变 → 安全 private LocalDateTime timestamp; // LocalDateTime不可变 → 安全 }结论全字段皆不可变浅克隆 100% 安全。深克隆纯属浪费 CPU。5.4 判断三如何落地避开 Javaclone()的坑虽然浅克隆够用但团队刻意避开了Object.clone()原因有三Cloneable是标记接口语义模糊clone()抛CloneNotSupportedException强制 try-catch破坏代码流畅性super.clone()返回Object需强制转型不优雅。他们选择更现代、更可控的方式构造函数注入原型。// 抽象原型接口更清晰的契约 public interface PrototypeT { T clone(); } // 具体原型实现用构造函数不碰 clone() public class OrderRequest implements PrototypeOrderRequest { private final Long userId; private final String skuCode; private final BigDecimal price; private final String couponId; private final String riskToken; private final LocalDateTime timestamp; // 标准构造函数用于创建原型 public OrderRequest(Long userId, String skuCode, BigDecimal price, String couponId, String riskToken, LocalDateTime timestamp) { this.userId userId; this.skuCode skuCode; this.price price; this.couponId couponId; this.riskToken riskToken; this.timestamp timestamp; } // 克隆构造函数关键用原型对象初始化新对象 public OrderRequest(OrderRequest prototype, Long newUserId, String newRiskToken) { // 复制所有不变字段 this.userId newUserId; // 只有 userId 和 riskToken 需变 this.skuCode prototype.skuCode; this.price prototype.price; this.couponId prototype.couponId; this.riskToken newRiskToken; this.timestamp LocalDateTime.now(); // 时间戳必须更新 } Override public OrderRequest clone() { // 这里可以灵活决定是返回新对象还是复用池中对象 return new OrderRequest(this, this.userId, this.riskToken); } }客户类下单入口// 预热创建一个标准原型只做一次 private static final OrderRequest PROTOTYPE new OrderRequest(0L, PHONE-PRO-2024, new BigDecimal(5999.00), COUPON-2024, RISK-TOKEN-DEFAULT, LocalDateTime.now()); // 秒杀时每请求克隆一次 public OrderRequest createOrderRequest(Long userId, String riskToken) { return PROTOTYPE.clone(); // 但等等——这里需要传入新 userId 和 riskToken }发现问题了吗clone()方法签名是OrderRequest clone()无法传参。于是团队微调把克隆逻辑外提由客户端决定定制化字段// 更实用的 API原型提供“定制化克隆”方法 public class OrderRequest { // ... 字段同上 // 标准克隆所有字段同原型 public OrderRequest clone() { return new OrderRequest(this, this.userId, this.riskToken); } // 定制化克隆只替换关键字段 public OrderRequest cloneWithUserId(Long newUserId) { return new OrderRequest(this, newUserId, this.riskToken); } public OrderRequest cloneWithRiskToken(String newRiskToken) { return new OrderRequest(this, this.userId, newRiskToken); } } // 客户端调用清晰、安全、无异常 public OrderRequest createOrderRequest(Long userId, String riskToken) { return PROTOTYPE.cloneWithUserId(userId).cloneWithRiskToken(riskToken); }5.5 效果与教训从 80ms 到 0.2ms 的跨越上线后监控显示OrderRequest创建耗时从均值 80ms 降至0.2ms提升 400 倍GC 压力下降 70%因不再频繁创建短生命周期对象代码可读性飙升createOrderRequest()方法体只剩一行逻辑一目了然。但最大的收获不是性能而是认知升级从那以后我每次设计需要高频创建的对象都强制走一遍“原型三问”它的字段是否都支持安全复制可复制性它的原型能否在克隆期间保持只读状态稳定性它的引用是否可迁移还是必须深挖依赖可迁移性问完这三句再决定用clone()、构造函数、Builder 模式还是老老实实new。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
Alexa语音交互技术:端到端SLU与复杂查询处理 1. Alexa语音交互背后的技术挑战每天早上被Alexa的闹钟叫醒时,我总会习惯性地问一句:"今天天气怎么样?"这个看似简单的交互背后,隐藏着复杂的语音理解技术栈。作为亚马逊实验室的前语音工程师,我想分享现代语… · 2026/11/3 20:22:51
联邦学习实战笔记:与边缘计算、区块链、迁移学习、强化学习的融合实践 联邦学习这个词这几年在圈子里被聊得很多,但真正把杨强老师那本《联邦学习实战》从头啃到尾的人其实没想象中那么多。我前后花了大概两个月时间把这本书过了两遍,第一遍是通读,第二遍是带着项目里遇到的实际问题去精读,尤其是第十… · 2026/11/3 20:22:51
AI编程Agent的拟人化状态机设计与职场模拟实验 1. 项目背景:AI编程Agent的职场PUA实验 这个在GitHub上获得7.5k星标的开源项目,用一种黑色幽默的方式重新定义了AI编程助手的工作模式。开发者将职场中常见的"PUA"管理手段移植到AI编程Agent上,创造了一个会"摆烂"也会被… · 2026/11/3 20:22:51
wxappUnpacker能力边界详解:能解什么、不能解什么 简介:这是一套面向小程序开发者与安全研究人员的微信小程序反编译工具集wxappUnpacker,专用于逆向解析小程序主包与分包,解决封闭环境下无法查看原始业务逻辑、组件结构及配置机制的痛点,适用于代码学习、性能分析、安全审计与问题… · 2026/11/4 13:00:42
舆情监测系统技术选型与实战优化指南 1. 舆情监测技术选型核心逻辑舆情监测系统的本质是"数据雷达",需要从海量异构数据中快速识别关键信号。我在2018年参与某省级政务舆情平台建设时,曾用传统爬虫方案导致关键舆情延迟6小时才被捕获,这个教训让我深刻认识到技术选型的… · 2026/11/4 13:00:42
大模型训练实战:从硬件选型到生产部署全解析 1. 大模型训练全景图:从理论到落地的完整路径 大模型训练早已不是实验室里的神秘黑箱,而是每个技术团队都能掌握的工程化能力。去年带队完成金融领域百亿参数模型训练时,我们踩过的坑比预想中多三倍——数据清洗耗时占整体60%,分布… · 2026/11/4 13:00:42
PyCharm专业版多平台安装与配置优化指南 1. 项目概述 PyCharm作为JetBrains公司推出的Python集成开发环境(IDE),在开发者群体中享有极高声誉。专业版相比社区版提供了更多高级功能,如科学计算工具、Web开发框架支持、数据库工具等,是专业Python开发者的首选工… · 2026/11/4 13:00:42
网页批量打印工具:绿色免安装Chrome内核方案 简介:这是一款面向办公人员、教师及资料整理者的绿色免安装网页批量打印工具,专为解决频繁打印多个网页时逐页操作低效、易出错的痛点。用户无需安装即可运行主程序,一键导入多个HTML页面并统一完成打印任务,显著提升报告汇编、教… · 2026/11/4 13:00:42
SQL日期函数详解:从基础到高级应用 1. 日期函数在SQL查询中的核心价值 日期处理是数据库操作中最常见也最容易出错的环节之一。记得刚入行时,我曾在月度报表统计中因为时区转换问题导致数据偏差30%,差点引发连锁反应。正是这类教训让我意识到,熟练掌握SQL日期函数不是可选项&am… · 2026/11/4 12:59:41
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38