惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Vercel News
Vercel News
Recorded Future
Recorded Future
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
M
MIT News - Artificial intelligence
云风的 BLOG
云风的 BLOG
Y
Y Combinator Blog
N
News | PayPal Newsroom
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Help Net Security
Help Net Security
博客园 - Franky
SecWiki News
SecWiki News
Recent Announcements
Recent Announcements
T
Troy Hunt's Blog
The Register - Security
The Register - Security
The Last Watchdog
The Last Watchdog
Webroot Blog
Webroot Blog
S
Security Affairs
博客园 - 司徒正美
S
Schneier on Security
I
InfoQ
博客园_首页
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Threat Research - Cisco Blogs
Forbes - Security
Forbes - Security
腾讯CDC
N
Netflix TechBlog - Medium
N
News and Events Feed by Topic
Cloudbric
Cloudbric
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
Recent Commits to openclaw:main
Recent Commits to openclaw:main
B
Blog
V
Vulnerabilities – Threatpost
C
Check Point Blog
Google DeepMind News
Google DeepMind News
Google Online Security Blog
Google Online Security Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
Cisco Blogs
Schneier on Security
Schneier on Security
O
OpenAI News
K
Kaspersky official blog

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
数字电路模拟程序的迭代设计与学习总结---三次作业复盘
CodeCatBatiao · 2026-06-24 · via 博客园_首页

数字电路模拟程序的迭代设计与学习总结---三次作业复盘

一、前言

这篇博客是对作业集4到作业集6的阶段性总结。三次作业的核心都围绕“数字电路模拟程序”展开,对应的题目分别是 NCHUD-数字电路模拟程序-1、NCHUD-数字电路模拟程序-2、NCHUD-数字电路模拟程序-4。虽然每次作业集从数量上看基本都是一道综合题,但实际写起来并不轻松,因为它考查的不是某一个单独语法点,而是把 Java 类设计、对象状态维护、字符串解析、集合使用、流程控制、异常判断和输出格式统一放进一个模拟类问题中。

从我自己的学习过程来看,这几次作业最大的难点不是“会不会写 if、for、ArrayList”,而是怎么把题目中的复杂规则拆成合适的类和方法。刚开始写程序-1时,我更多关注的是能不能让样例跑通;到了程序-2,题目增加了更多复杂元件,我开始发现原来的写法扩展起来比较吃力;到了程序-4,加入子电路和异常检测后,如果不拆分类职责,代码基本很难继续维护。

本次整理中,我读取并核对了三份当前源码的数据。数字电路模拟程序-1 的代码为 280 行,主要类有 Gate、Connection、Main;数字电路模拟程序-2 的代码为 442 行,主要类有 Gate、Connection、Circuit、Main;数字电路模拟程序-4 的代码为 611 行,主要类增加到十多个,包括 Gate、RawConnection、Connection、CircuitDefinition、CircuitHelper、PinInfo、InputReader、ErrorChecker、CircuitBuilder、Simulator、OutputPrinter、Main 等。

题目 当前源码行数 主要类数量 主要任务
数字电路模拟程序-1 280 行 3 个类 基础逻辑门、连接传播、排序输出
数字电路模拟程序-2 442 行 4 个类 增加复杂元件,封装电路管理
数字电路模拟程序-4 611 行 约 12 个类 子电路、异常检测、构建与模拟分离

其中,程序-1 的最后一次提交结果为 95/100,最后一个多层级联电路测试点 case40 出现 Non-zero Exit Code,得分为 0/5。这个数据对我来说很有提醒意义:程序不是完全不能跑,而是在复杂场景下还有稳定性问题。程序-2和程序-4部分,我这次主要依据已读取到的题面和右侧当前源码进行分析,没有核对到的评测分数不在文中随便写。

源码数据与类结构图

本次分析主要依据三份已读取源码和题面内容,未核对到的数据不单独编写。整体变化如下:

题目 源码行数 主要类数量 重点变化
程序-1 280 行 3 个 基础门电路、连接传播、排序输出
程序-2 442 行 4 个 增加复杂元件,开始封装 Circuit
程序-4 611 行 约 12 个 加入子电路、异常检测和分层处理
代码规模:280行 -> 442行 -> 611行
类数量:  3个  -> 4个  -> 约12个

程序-1类结构较集中,Main 负责读取、创建对象和输出,Gate 保存门电路状态,Connection 保存连接关系。

程序-1类结构
Main
 ├─ Gate:编号、类型、输入值、输出值、计算逻辑
 └─ Connection:起点、终点、信号传递关系

程序-2增加复杂元件后,把一部分电路管理交给 Circuit,代码比程序-1清楚一些,但 Gate 内部承担的类型判断仍然偏多。

程序-2类结构
Main
 └─ Circuit
     ├─ Gate:基础门、三态门、译码器、选择器等
     └─ Connection:元件之间的连线

程序-4的结构变化最大,输入读取、错误检查、构建、模拟、输出被拆成多个类,维护性比前两题更好。

程序-4类结构
InputReader -> CircuitDefinition -> ErrorChecker
                              └-> CircuitBuilder -> Simulator -> OutputPrinter
CircuitBuilder 使用 Gate、Connection、RawConnection、PinInfo 等对象完成构建

程序-1最后一次提交为 95/100,失败点是 case40 多层级联电路,状态为 Non-zero Exit Code,该点 0/5;运行数据为 21632 KB、130 ms / 800 ms。这个结果说明基础逻辑基本通过,但多层传播仍有稳定性问题。

二、设计与分析

1. 数字电路模拟程序-1:先把基础逻辑门跑起来

程序-1是整个系列的基础版本。题目要求模拟五种基础逻辑门:与门 A、或门 O、非门 N、异或门 X、同或门 Y。输入信息主要分成两类:一类是 INPUT 开头的初始输入信号,另一类是中括号形式的连接信息。程序需要把初始信号按照连接关系传递到元件引脚上,当某个元件的输入引脚都有效后,再计算它的输出,并继续传播到下一级元件。

这一版我的代码主要设计了三个类。Gate 类用于保存元件信息,包括元件类型、名称、编号、输入引脚数量、输入数组、是否完成计算、输出值等。Connection 类用于保存连接关系,也就是信号从哪里来、要传到哪个引脚。Main 类承担了主要流程,包括输入解析、查找元件、创建元件、发送信号、计算输出和排序打印。

程序-1的大致流程可以概括为:

读取 INPUT 初始信号
读取连接信息
根据连接信息创建 Gate 对象
把输入信号写入目标元件引脚
循环扫描所有 Gate,判断是否可以计算
计算输出后继续沿连接关系传播
按 A、O、N、X、Y 顺序排序输出

从设计上看,这一版代码更偏过程式。虽然我定义了 Gate 和 Connection,但是 Gate 更像一个数据容器,真正的逻辑基本还是放在 Main 里。比如 findGate、sendValue、getOrCreate、sortById、printList 等方法都在 Main 中。这样写的好处是简单直接,写的时候不用考虑太多结构;坏处是后期功能一多,Main 类会越来越重。

程序-1最终提交是 95/100,说明大部分基础测试是能通过的,比如单个门、多输入门、简单级联、部分复杂连接等。但是 case40 的多层级联电路出现 Non-zero Exit Code,说明程序在深层传播时还有漏洞。我分析原因可能与信号传播方式有关。当前逻辑是循环扫描所有元件,判断哪些元件已经准备好。如果电路层次比较深,或者某些输出需要多次传播,程序就可能出现状态更新不及时、漏传播、提前计算等问题。

这道题让我认识到,模拟类题目不能只靠“能跑样例”判断是否稳定。基础样例通过,只能说明规则的大方向对了;复杂测试点才会暴露设计上的问题。程序-1如果后续要改进,我认为应该把信号传播改成队列式流程。初始输入先进入队列,每次取出一个信号,找到它连接到的目标引脚,写入后判断目标元件是否已经可以计算。如果可以计算,就把输出继续加入队列。这样比反复扫描所有元件更清晰,也更适合处理多层级联。

2. 数字电路模拟程序-2:复杂元件带来扩展压力

程序-2是在程序-1基础上的扩展版本。除了原来的五种基础逻辑门,题目还增加了三态门、译码器、数据选择器、数据分配器。这个变化让题目难度明显提高,因为每一种新增元件的引脚规则都不同,不再只是简单的 0 和 1 计算。

例如,三态门有输入引脚和控制引脚,当控制端有效时输出等于输入,当控制端无效时输出为无效状态。译码器需要根据多个输入引脚的编码决定哪一路输出有效,还要考虑控制引脚是否满足条件。数据选择器需要根据控制端选择某一路输入作为输出,数据分配器则是把一路输入分配到多路输出中的某一路。也就是说,程序-2已经不只是基础逻辑门的组合,而是开始接近更复杂的数字电路元件模拟。

这一版代码为 442 行,主要类有 Gate、Connection、Circuit、Main。和程序-1相比,最大的变化是增加了 Circuit 类。Circuit 类负责管理整个电路中的输入、元件、连接关系和模拟流程。Main 类不再承担全部细节,而是负责读入数据并调用 Circuit 中的方法。

这一版结构大致可以表示为:

Main
-> Circuit
-> Gate
-> Connection

Circuit 中包含输入解析、连接解析、元件创建、信号发送、模拟运行和结果输出等方法。相比程序-1所有逻辑都放在 Main 里,这样的结构已经清楚了不少。至少从阅读代码的角度看,可以知道电路整体管理逻辑在 Circuit 中,而不是到处散落。

但是程序-2也暴露出另一个问题:虽然代码拆出了 Circuit 类,但不同元件的计算逻辑仍然主要依赖类型字符进行判断。比如根据 A、O、N、X、Y、S、M、Z、F 等类型进入不同计算分支。这种写法能完成当前任务,但扩展性一般。如果以后继续增加元件,compute 相关逻辑会越来越长。

从面向对象角度看,更好的方式应该是使用继承和多态。可以定义一个抽象的 Gate 父类,再让 AndGate、OrGate、NotGate、TriStateGate、Decoder、Mux、Demux 等子类分别实现自己的 compute 方法。这样 Circuit 只负责调度,不需要知道每一种门内部如何计算。当然,以我当前学习阶段来说,程序-2能先把 Circuit 拆出来已经是一种进步,但多态思想还没有真正落实。

程序-2让我体会到,代码设计不能只看当前题目能不能过,还要看下一步是否容易扩展。如果一个新规则加入后,需要大范围修改旧代码,就说明原来的职责划分还不够好。

3. 数字电路模拟程序-4:子电路和异常检测让结构变复杂

程序-4是这三道题中综合性最强的一题。它不是继续增加更多基础元件,而是在程序-1基础上增加了子电路和异常输入检测两个功能。这个变化让题目从“计算电路输出”进一步变成了“管理复杂电路结构”。

子电路的定义格式类似 C1:、INPUT、OUT、若干连接信息、endc。主电路可以通过 C1-A、C1-B、C1-C 这样的形式引用子电路的输入和输出。输出时,子电路内部元件还要带上子电路编号,例如 C1-A(2)1-0:0。这个要求说明子电路不是普通字符串,而是一个包含输入、输出、内部元件和内部连接的组合结构。

程序-4 的代码规模为 611 行,类的数量也明显增加。主要类和职责如下:

类名 主要职责
Gate 表示基础逻辑元件
RawConnection 保存原始连接文本
Connection 保存处理后的连接关系
CircuitDefinition 保存主电路或子电路定义
CircuitHelper 处理元件名、引脚类型、格式判断等辅助逻辑
PinInfo 保存解析后的引脚信息
InputReader 读取子电路和主电路输入
ErrorChecker 负责异常输入检测
CircuitBuilder 构建实际用于模拟的电路结构
Simulator 负责信号传播和计算
OutputPrinter 按题目要求输出结果
Main 程序入口

从结构上看,这一版已经明显比前两版更模块化。InputReader 负责读取,ErrorChecker 负责检查错误,CircuitBuilder 负责把主电路和子电路构造成可模拟的结构,Simulator 负责运行模拟,OutputPrinter 负责输出结果。这样一来,Main 类只需要串联整体流程。

程序-4的大致流程可以整理为:

读取所有子电路定义
读取主电路定义
对连接信息进行异常检测
根据主电路和子电路构建实际元件与连接
发送初始输入信号
运行模拟器进行信号传播
按题目要求输出结果

这一版最难的地方,我认为有两个。第一个是子电路命名空间问题。主电路里可能有 N1,子电路里也可能有 N1,如果不做区分,它们在集合中就会冲突。因此代码需要给子电路内部元件加上子电路编号前缀,保证每个元件在全局模拟时都是唯一的。第二个是异常检测。题目要求判断一个连接信息中是否包含多个输入、是否没有输入、是否没有输出、输入输出顺序是否错误、输入引脚是否冲突等。这些错误有时还会同时出现,必须按题目要求的优先级输出。

程序-4让我比较明显地感受到,面向对象设计不是为了“看起来高级”,而是为了让复杂问题可拆、可查、可改。如果把子电路展开、异常检测、信号模拟全写在 Main 里,代码会非常难维护。拆成多个类之后,虽然总行数增加到了 611 行,但每一部分的责任更清楚,调试时也更容易定位。

三、踩坑心得

1. 字符串解析不能随手写

三道题里最频繁出现的问题就是字符串解析。像 A(2)1-1、X1-0、C1-A、[A A(2)1-1] 这些格式看起来都不长,但含义差别很大。刚开始我习惯直接使用 split 和 substring,样例简单时能跑,格式一复杂就容易出错。

比如在程序-4里,C1-A 可能表示子电路输入,C1-N1-0 又可能表示子电路内部元件输出。如果没有统一的解析规则,很容易把两种东西混在一起。后面我才意识到,解析逻辑应该集中处理,先判断是不是元件引脚,再判断是输入引脚还是输出引脚,再判断是否属于子电路。这样代码会多一些,但比到处临时拆字符串更可靠。

2. 程序-1的 95 分说明基础能跑不代表结构稳定

程序-1拿到 95/100 时,我一开始觉得只差 5 分,问题应该不大。但后来回头看,这个失败点其实暴露的是结构问题。大部分测试点能过,说明基础规则处理得差不多;但多层级联电路失败,说明传播流程在复杂场景下不够稳定。

这个问题不是简单多加几个判断就能彻底解决的。它更像是设计上的问题:信号应该如何传播,元件什么时候计算,输出什么时候继续传递,这些都应该有明确流程。如果只是不断扫描所有元件,复杂情况下就可能漏掉某些状态变化。

3. 类拆分不是为了凑数量

程序-1只有三个类,写起来快,但 Main 类太重。程序-4有十二个左右的类,看起来复杂,但每个类职责更明确。以前我对“单一职责”的理解比较浅,觉得类拆多了只是形式。做完这几道题后,我发现类拆分真正的意义是降低维护难度。

当输入读取、错误检测、构建、模拟、输出都混在一起时,出错后很难判断问题在哪里。拆开以后,至少能先判断问题大概出在读取阶段、检查阶段还是模拟阶段。

4. 子电路需要命名空间意识

程序-4中,子电路内部的元件名可能和主电路重复。如果直接用原始名称保存,后面查找和输出都会混乱。因此需要给子电路内部元件加上前缀,例如 C1-N1。这个问题让我第一次比较具体地理解了“命名空间”的作用。

5. 异常检测要考虑优先级

异常检测不是发现错误就随便输出,而是要符合题目规定。有些连接信息可能同时满足多种错误情况,比如既存在多个输入,又没有合法输出。如果判断顺序不对,输出的错误类型就会和题目要求不一致。这个地方也说明我的测试习惯还不够好,应该提前整理更多异常样例,而不是只靠提交后的结果判断。

四、改进建议

1. 程序-1改用队列式信号传播

程序-1最需要改进的是信号传播方式。可以把初始输入和元件输出都看成待传播信号,放入队列中统一处理。每次从队列中取出一个信号,发送到所有目标引脚。如果目标元件输入完整,就计算输出并继续入队。这样比循环扫描所有元件更直观,也更适合多层级联。

2. 程序-2引入继承和多态

程序-2中元件类型已经很多,如果继续使用类型字符判断,代码会越来越长。后续可以定义抽象 Gate 类,再让不同元件继承它,各自实现 compute 方法。这样 Circuit 只负责调度,具体怎么算交给具体元件类处理。

3. 程序-4优化错误类型设计

程序-4的 ErrorChecker 还可以继续优化。可以把错误类型设计成统一枚举或常量,例如 MORE_THAN_ONE_INPUT、NONE_INPUT、NONE_OUTPUT、SEQUENCE_ERROR、INPUT_CONFLICT。这样错误判断和错误输出可以分离,后续增加规则时也更好维护。

4. 建立本地测试样例库

这几道题让我意识到本地测试很重要。后续应该自己整理测试样例,包括单个基础门、多输入门、多层级联、多分支连接、子电路调用、输入冲突、输入输出顺序错误等。每次修改代码后先在本地跑一遍,再提交 PTA,效率会比盲目提交高很多。

五、总结

这三次作业让我对 Java 面向对象有了更实际的认识。程序-1让我完成了基础逻辑门模拟,也暴露出 Main 类过重和复杂级联不稳定的问题。程序-2让我开始把电路整体封装到 Circuit 类中,逐渐意识到模块化的重要性。程序-4进一步加入子电路和异常检测,让我真正感受到复杂程序必须先分析对象、关系和流程,再开始写代码。

从 280 行到 442 行,再到 611 行,代码规模不断增加。如果没有类的拆分,后面很难继续维护。虽然目前代码还有不少不足,比如多态使用不充分、部分解析逻辑偏复杂、本地测试不够系统,但相比刚开始,我对对象、职责、流程这些概念的理解更清楚了。

后续我还需要继续学习继承、多态、接口、异常处理和设计模式,尤其是组合模式和事件驱动模拟这类思想。对我来说,这一阶段最大的收获不是某一个语法点,而是明白了复杂题目不能一上来就写代码,应该先分析数据结构和业务流程。结构想清楚了,代码才不会越写越乱。