【C++架构师级精讲】工厂模式实战:从游戏角色到披萨店
前言还记得初次接触工厂模式时各种产品、具体工厂、抽象产品等专业术语让我一头雾水。直到我通过游戏角色创建和披萨店运营这两个生活化案例来理解才真正掌握其精髓。本文将通过通俗易懂的讲解和完整的C代码示例系统讲解简单工厂、工厂方法和抽象工厂三种设计模式。一、为什么需要工厂模式传统创建方式的痛点假设你在开发一款RPG游戏需要创建不同角色// 游戏主流程中分散的创建代码 int main() { // 玩家选择战士 Warrior* player new Warrior(); player-attack(); // 任务NPC创建法师 Mage* npc new Mage(); npc-castSpell(); // Boss战创建弓箭手 Archer* boss new Archer(); boss-shoot(); // 维护痛点 // 1. 删除战士职业需要修改所有new Warrior()的地方 // 2. 新增职业需要修改多处创建逻辑 return 0; }主要问题创建逻辑分散维护困难客户端与具体类高度耦合违反开闭原则扩展需修改现有代码工厂模式的核心价值封装对象创建过程让客户端只需关注使用什么而不用关心如何创建。二、简单工厂模式角色创建中心2.1 生活案例餐厅点餐在餐厅点餐时你只需告诉服务员要一份芝士披萨服务员会向后厨下单。你不需要知道披萨的具体做法和厨师是谁。这里的服务员就是简单工厂。2.2 游戏实现统一角色创建#include iostream #include memory #include string // 角色基类 class Character { public: virtual ~Character() default; virtual void attack() 0; virtual std::string getClassName() 0; }; // 具体角色 class Warrior : public Character { public: void attack() override { std::cout ⚔️ 战士旋风斩造成150点伤害\n; } std::string getClassName() override { return 战士; } }; class Mage : public Character { public: void attack() override { std::cout 法师火球术造成200点魔法伤害\n; } std::string getClassName() override { return 法师; } }; class Archer : public Character { public: void attack() override { std::cout 弓箭手三重射击造成120点伤害\n; } std::string getClassName() override { return 弓箭手; } }; // 简单工厂 class SimpleCharacterFactory { public: static std::unique_ptrCharacter createCharacter(const std::string type) { if (type warrior) return std::make_uniqueWarrior(); if (type mage) return std::make_uniqueMage(); if (type archer) return std::make_uniqueArcher(); throw std::invalid_argument(无效职业 type); } }; // 使用示例 int main() { std::cout 简单工厂模式演示 \n\n; // 创建战士角色 auto player SimpleCharacterFactory::createCharacter(warrior); std::cout 创建职业 player-getClassName() \n; player-attack(); // 创建法师NPC auto npc SimpleCharacterFactory::createCharacter(mage); std::cout 创建职业 npc-getClassName() \n; npc-attack(); return 0; }输出结果 简单工厂模式演示 创建职业战士 ⚔️ 战士旋风斩造成150点伤害 创建职业法师 法师火球术造成200点魔法伤害2.3 披萨店实现#include iostream #include memory #include string // 披萨基类 class Pizza { public: virtual ~Pizza() default; virtual void prepare() 0; virtual void bake() { std::cout 烘烤15分钟\n; } virtual void box() { std::cout 装盒完成\n; } }; // 具体披萨 class CheesePizza : public Pizza { public: void prepare() override { std::cout 芝士披萨加入马苏里拉芝士、番茄酱\n; } }; class PepperoniPizza : public Pizza { public: void prepare() override { std::cout 腊肠披萨加入意式辣味腊肠、芝士\n; } }; // 简单工厂 class SimplePizzaFactory { public: static std::unique_ptrPizza createPizza(const std::string type) { if (type cheese) return std::make_uniqueCheesePizza(); if (type pepperoni) return std::make_uniquePepperoniPizza(); throw std::invalid_argument(无此披萨类型); } }; // 披萨店 class PizzaStore { public: void orderPizza(const std::string type) { auto pizza SimplePizzaFactory::createPizza(type); std::cout \n制作 type 披萨\n; pizza-prepare(); pizza-bake(); pizza-box(); } }; int main() { PizzaStore store; store.orderPizza(cheese); store.orderPizza(pepperoni); return 0; }2.4 模式总结优势实现简单集中管理创建逻辑客户端只需传入参数无需了解创建细节局限新增产品类型需要修改工厂类产品类型多时工厂类会臃肿适用场景产品类型较少且稳定的简单项目三、工厂方法模式专业化创建3.1 生活案例连锁披萨店假设你经营全国连锁披萨店纽约分店制作薄底披萨芝加哥分店制作深盘披萨。总部制定准备→烘烤→装盒的标准流程但各分店自行实现具体制作方法。3.2 游戏实现职业训练营#include iostream #include memory #include string // 角色基类 class Character { public: virtual ~Character() default; virtual void attack() 0; virtual std::string getClassName() 0; }; class Warrior : public Character { public: void attack() override { std::cout ⚔️ 战士英勇打击\n; } std::string getClassName() override { return 战士; } };class Archer : public Character { public: void attack() override { std::cout 弓箭手箭雨\n; } std::string getClassName() override { return 弓箭手; } }; // 抽象工厂训练营 class CharacterFactory { public: virtual ~CharacterFactory() default; // 工厂方法由子类实现具体角色创建 virtual std::unique_ptrCharacter createCharacter() 0; // 模板方法定义标准训练流程 void trainCharacter() { auto character createCharacter(); std::cout 训练 character-getClassName() 完成\n; character-attack(); std::cout -------------------\n; } }; // 具体工厂职业训练营 class WarriorFactory : public CharacterFactory { public: std::unique_ptrCharacter createCharacter() override { return std::make_uniqueWarrior(); } }; class MageFactory : public CharacterFactory { public: std::unique_ptrCharacter createCharacter() override { return std::make_uniqueMage(); } }; class ArcherFactory : public CharacterFactory { public: std::unique_ptrCharacter createCharacter() override { return std::make_uniqueArcher(); } }; // 使用示例 int main() { std::cout 工厂方法模式演示 \n\n; // 初始化各职业训练营 WarriorFactory warriorCamp; MageFactory mageCamp; ArcherFactory archerCamp; // 执行训练流程 warriorCamp.trainCharacter(); mageCamp.trainCharacter(); archerCamp.trainCharacter(); // 扩展说明只需添加新工厂类即可支持新职业 // 示例class PriestFactory : public CharacterFactory { ... }; return 0; }运行结果 工厂方法模式演示 训练战士完成 ⚔️ 战士英勇打击 ------------------- 训练法师完成 法师暴风雪 ------------------- 训练弓箭手完成 弓箭手箭雨 -------------------3.3 披萨店实现#include iostream #include memory // 披萨基类 class Pizza { public: virtual ~Pizza() default; virtual void prepare() 0; virtual void bake() 0; virtual void box() { std::cout 装盒\n; } }; // 纽约风味披萨 class NYStyleCheesePizza : public Pizza { public: void prepare() override { std::cout 纽约芝士披萨薄底、新鲜马苏里拉\n; } void bake() override { std::cout 砖炉高温快烤10分钟\n; } }; // 芝加哥风味披萨 class ChicagoStyleCheesePizza : public Pizza { public: void prepare() override { std::cout ️ 芝加哥深盘芝士披萨厚底、大量芝士\n; } void bake() override { std::cout 深烤盘慢烤45分钟\n; } }; // 抽象披萨店 class PizzaStore { public: virtual ~PizzaStore() default; // 标准制作流程模板方法 void orderPizza() { auto pizza createPizza(); std::cout \n getStoreName() \n; pizza-prepare(); pizza-bake(); pizza-box(); std::cout 请享用\n; } protected: // 工厂方法由子类实现具体披萨类型 virtual std::unique_ptrPizza createPizza() 0; virtual std::string getStoreName() 0; }; // 纽约分店 class NYPizzaStore : public PizzaStore { protected: std::unique_ptrPizza createPizza() override { return std::make_uniqueNYStyleCheesePizza(); } std::string getStoreName() override { return 纽约曼哈顿店; } }; // 芝加哥分店 class ChicagoPizzaStore : public PizzaStore { protected: std::unique_ptrPizza createPizza() override { return std::make_uniqueChicagoStyleCheesePizza(); } std::string getStoreName() override { return 芝加哥深盘总店; } }; int main() { NYPizzaStore nyStore; ChicagoPizzaStore chicagoStore; nyStore.orderPizza(); chicagoStore.orderPizza(); return 0; }3.4 工厂方法模式总结核心思想将对象创建委托给子类由子类决定实例化哪个具体类。优点符合开闭原则便于扩展新产品客户端仅依赖抽象接口缺点每个产品需对应一个工厂类增加系统复杂度适用场景需要灵活扩展产品类型的系统四、抽象工厂模式装备套装系统4.1 生活类比统一供应链经营高端披萨连锁时需确保意大利分店使用全套意式原料有机分店使用全套有机食材禁止跨系列原料混用4.2 游戏实现套装装备#include iostream #include memory #include string // 抽象武器 class Weapon { public: virtual ~Weapon() default; virtual void use() 0; }; // 具体武器 class Sword : public Weapon { public: void use() override { std::cout ️ 挥动长剑\n; } }; class Staff : public Weapon { public: void use() override { std::cout 挥舞法杖\n; } }; class Bow : public Weapon { public: void use() override { std::cout 拉弓射箭\n; } }; // 抽象防具 class Armor { public: virtual ~Armor() default; virtual void equip() 0; }; // 具体防具 class HeavyArmor : public Armor { public:class Robe : public Armor { public: void equip() override { std::cout 装备法袍魔力50\n; } }; class LeatherArmor : public Armor { public: void equip() override { std::cout 装备皮甲敏捷50\n; } }; // 装备套装抽象工厂 class EquipmentFactory { public: virtual ~EquipmentFactory() default; virtual std::unique_ptrWeapon createWeapon() 0; virtual std::unique_ptrArmor createArmor() 0; }; // 战士装备工厂 class WarriorEquipmentFactory : public EquipmentFactory { public: std::unique_ptrWeapon createWeapon() override { return std::make_uniqueSword(); } std::unique_ptrArmor createArmor() override { return std::make_uniqueHeavyArmor(); } }; // 法师装备工厂 class MageEquipmentFactory : public EquipmentFactory { public: std::unique_ptrWeapon createWeapon() override { return std::make_uniqueStaff(); } std::unique_ptrArmor createArmor() override { return std::make_uniqueRobe(); } }; // 弓箭手装备工厂 class ArcherEquipmentFactory : public EquipmentFactory { public: std::unique_ptrWeapon createWeapon() override { return std::make_uniqueBow(); } std::unique_ptrArmor createArmor() override { return std::make_uniqueLeatherArmor(); } }; // 使用装备工厂的角色类 class GameCharacter { private: std::unique_ptrWeapon weapon; std::unique_ptrArmor armor; std::string name; public: GameCharacter(const std::string name, std::unique_ptrEquipmentFactory factory) : name(name) { weapon factory-createWeapon(); armor factory-createArmor(); } void showEquipment() { std::cout \n角色 name \n; std::cout 装备检查\n; weapon-use(); armor-equip(); std::cout --- 装备成套属性匹配 ✅ ---\n; } }; int main() { std::cout 抽象工厂模式演示 \n; // 创建战士角色 GameCharacter warrior(亚瑟, std::make_uniqueWarriorEquipmentFactory()); warrior.showEquipment(); // 创建法师角色 GameCharacter mage(甘道夫, std::make_uniqueMageEquipmentFactory()); mage.showEquipment(); // 创建弓箭手角色 GameCharacter archer(莱戈拉斯, std::make_uniqueArcherEquipmentFactory()); archer.showEquipment(); return 0; }运行结果 抽象工厂模式演示 角色亚瑟 装备检查 ️ 挥动长剑 ️ 装备重甲防御50 --- 装备成套属性匹配 ✅ --- 角色甘道夫 装备检查 挥舞法杖 装备法袍魔力50 --- 装备成套属性匹配 ✅ --- 角色莱戈拉斯 装备检查 拉弓射箭 装备皮甲敏捷50 --- 装备成套属性匹配 ✅ ---4.3 披萨店原料供应链实现#include iostream #include memory // 抽象原料工厂 class IngredientFactory { public: virtual ~IngredientFactory() default; virtual std::string createDough() 0; virtual std::string createSauce() 0; virtual std::string createCheese() 0; }; // 意大利原料工厂 class ItalianIngredientFactory : public IngredientFactory { public: std::string createDough() override { return 意大利00号面粉; } std::string createSauce() override { return 圣马扎诺番茄酱; } std::string createCheese() override { return 帕尔马芝士; } }; // 有机原料工厂 class OrganicIngredientFactory : public IngredientFactory { public: std::string createDough() override { return 有机全麦面粉; } std::string createSauce() override { return 有机番茄酱; } std::string createCheese() override { return 有机马苏里拉; } }; // 披萨类 class Pizza { private: std::unique_ptrIngredientFactory factory; public: Pizza(std::unique_ptrIngredientFactory f) : factory(std::move(f)) {} void prepare() { std::cout 制作披萨\n; std::cout 面团 factory-createDough() \n; std::cout 酱料 factory-createSauce() \n; std::cout 芝士 factory-createCheese() \n; std::cout 所有原料来自同一产地 ✅\n; } }; int main() { std::cout 意大利风情店 \n; Pizza italianPizza(std::make_uniqueItalianIngredientFactory()); italianPizza.prepare(); std::cout \n 有机健康店 \n; Pizza organicPizza(std::make_uniqueOrganicIngredientFactory()); organicPizza.prepare(); return 0; }4.4 抽象工厂模式总结核心思想创建相关对象系列确保产品兼容性。优点保证产品族一致性客户端与具体产品解耦缺点扩展新产品需修改接口适用场景需要成套产品的场景UI组件、游戏装备等五、三种模式核心对比5.1 核心概念速览// 简单工厂通过字符串参数创建对象 auto character SimpleFactory::create(warrior); // 工厂方法每个产品对应专属工厂 WarriorFactory factory; auto character factory.create(); // 抽象工厂创建配套产品系列 WarriorEquipmentFactory equipFactory; auto weapon equipFactory.createWeapon(); // 配套武器 auto armor equipFactory.createArmor(); // 配套防具5.2 模式选择指南使用场景推荐模式产品类型少且稳定5种简单工厂需要频繁扩展产品线工厂方法⭐需要确保产品兼容性抽象工厂快速开发原型直接实例化5.3 架构关系图解简单工厂 客户端 → [中央工厂] → 产品A/产品B/产品C (集中式生产) 工厂方法 客户端 → 抽象工厂接口 ├→ 工厂A → 产品A ├→ 工厂B → 产品B └→ 工厂C → 产品C (分散式生产) 抽象工厂 客户端 → 抽象工厂接口 ├→ 工厂X → 产品X1 产品X2 └→ 工厂Y → 产品Y1 产品Y2 (系列化生产)六、最佳实践6.1 应用场景判断代码中充斥new ConcreteClass()→ 考虑简单工厂需要根据条件创建不同对象→ 采用工厂方法需要保持多对象风格一致→ 使用抽象工厂6.2 C实现要点// ✅ 最佳实践使用智能指针管理资源 virtual std::unique_ptrProduct create() 0; // ✅ 推荐C17智能指针构造 return std::make_uniqueConcreteProduct(); // ❌ 反模式返回原始指针 virtual Product* create() 0; // 存在内存泄漏风险6.3 常见误区警示避免过度使用简单场景直接实例化更合适模式认知简单工厂是编程范式非GoF标准模式设计平衡模式应用应以实际需求为准七、代码资源完整可编译的C17示例代码已就绪。编译指令# 简单工厂 g -stdc17 simple_factory.cpp -o simple_factory ./simple_factory # 工厂方法 g -stdc17 factory_method.cpp -o factory_method ./factory_method # 抽象工厂 g -stdc17 abstract_factory.cpp -o abstract_factory ./abstract_factory核心总结本质原则通过工厂模式实现对象创建与使用的解耦。简单工厂中央集权式生产工厂方法专业分工式生产抽象工厂系列配套式生产形象记忆法简单工厂是职业选择器、工厂方法是专业培训营、抽象工厂是风格套装生成器。掌握这个类比面试游刃有余推荐阅读《Head First 设计模式》GoF《设计模式可复用面向对象软件的基础》希望本指南助你彻底掌握工厂模式如果觉得有帮助欢迎点赞收藏~

相关新闻

做小游戏,光有玩法还不够:4个项目的新进展

做小游戏,光有玩法还不够:4个项目的新进展

大家好,我是晓衡。 最近,几位合作开发者带来了新东西:3D 解绳游戏源码、试玩广告打包工具,还有消除游戏的新版本和动物解谜游戏的关卡编辑器。 今天一起整理给大家。正在找小游戏项目、研究玩法,或者有二次开发需求的朋…

2026/10/15 2:59:33 阅读更多 →
稀疏的代价:当测量矩阵也要“瘦身“,我们还能找回原来的信号吗

稀疏的代价:当测量矩阵也要“瘦身“,我们还能找回原来的信号吗

想象你在整理一份很长很长的问卷调查,一千个人填了一千份答案,但每个人只回答了其中几个问题。现在你想根据这些零零散散的回答,猜出问卷设计者最初想调查的到底是哪些关键议题。这听起来是不是有点像大海捞针?这正是压缩感知这个…

2026/10/15 2:58:33 阅读更多 →
研发团队战斗力不是交付快:从可预测到能复利的系统性建设

研发团队战斗力不是交付快:从可预测到能复利的系统性建设

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 2:58:33 阅读更多 →

最新新闻

Java接入个人微信API:消息回调进客服系统的正确姿势

Java接入个人微信API:消息回调进客服系统的正确姿势

Java 团队接个人微信,通常第一反应是:Spring Boot 写个 Controller,接收回调,然后直接在方法里写业务。 本地调试挺顺,一上生产就出现:接口超时、消息重复、Tomcat 线程打满。 问题不在 Java,而…

2026/10/15 3:33:41 阅读更多 →
YOLO26算法室内工作环境手部手势目标检测+训练好的模型+8212张数据集+pyqt可视化界面

YOLO26算法室内工作环境手部手势目标检测+训练好的模型+8212张数据集+pyqt可视化界面

YOLO26算法室内工作环境手部手势目标检测训练好的模型8212张数据集pyqt可视化界面 这套数据共 8212 张图。用 YOLO26 训了 100 轮,mAP50 0.7315,mAP50-95 0.6002。Precision 0.7335、Recall 0.7532。下面按数据构成 → 训练曲线 → 预测效果的顺序过一遍…

2026/10/15 3:33:41 阅读更多 →
仓颉编程语言 I/O 节点流完全指南:标准流与文件流的实战解析

仓颉编程语言 I/O 节点流完全指南:标准流与文件流的实战解析

文档知识库教程OpenHarmony 【免费下载链接】CangjieCorpus 本仓库为仓颉编程语言语料库,聚焦 仓颉编程语言 核心知识体系,整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源,经结构化处理与专业标注,构建为支持 R…

2026/10/15 3:33:41 阅读更多 →
LAMMPS bond_style mm3 键伸缩势详解:YAFF 包的 MM3 非谐势实现、参数配置与实战应用

LAMMPS bond_style mm3 键伸缩势详解:YAFF 包的 MM3 非谐势实现、参数配置与实战应用

科研科学计算高性能计算 【免费下载链接】lammps Public development project of the LAMMPS MD software package 项目地址: https://gitcode.com/gh_mirrors/la/lammps 点击查看 免费下载 导读 bond_style mm3 是 LAMMPS 中用于描述键伸缩运动的非谐势模型&…

2026/10/15 3:33:41 阅读更多 →
Flutter Engine Windows 无障碍实现解析:MSAA 与 UI Automation 在 AXPlatformNodeWin 中的落地

Flutter Engine Windows 无障碍实现解析:MSAA 与 UI Automation 在 AXPlatformNodeWin 中的落地

跨平台前端移动开发OpenHarmony 【免费下载链接】flutter_flutter 本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于…

2026/10/15 3:33:41 阅读更多 →
Natron ErodeSmooth 节点完全指南:归一化功率加权腐蚀/膨胀滤镜的参数解析与源码级解读

Natron ErodeSmooth 节点完全指南:归一化功率加权腐蚀/膨胀滤镜的参数解析与源码级解读

音视频视频处理图形学桌面应用 【免费下载链接】Natron Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry. 项目地址: https://gitcode.com/gh_mirrors/na/Natron 点击查看 …

2026/10/15 3:32:41 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →