题目集5~7 单部电梯调度——三周血泪实录
作者:曾建东 | 南昌航空大学 软件工程大一
时间:2025‑04‑20
1. 前言|先吐个槽
还记得第一次看到“单部电梯调度”这行标题的时候,我心里是窃喜的:
“电梯不就是 while 循环 + if 判断方向?分分钟写完。”
结果真正动手才发现——真正难的不是能跑,而是跑得对、跑得快、还能持续改。
三周、三张类图、三次 PTA 红叉、无数次 IDEA 运行……电梯把我从“写得动”打到“会怀疑人生”再到“勉强看懂自己写的代码”。
下面这张表是我给自己做的小统计▼
| 版本 | 题目编号 | 新增要求 | 文件/类 数 | 代码行数¹ | PTA 首提交得分 | 心情 |
|---|---|---|---|---|---|---|
| V1 | 5‑5 | 跑通最基本的单电梯 | 2 | 320 | 70/100 | 🙂 “原来如此” |
| V2 | 6‑3 | 按 SRP 拆类 | 6 | 450 | 50/100 | 😵 “Bug 炸裂” |
| V3 | 7‑3 | 加 Passenger + 新输入格式 | 7 | 530 | 80/100 | 😌 “总算像样” |
¹ 行数是 SourceMonitor 报表里的 Lines,不含空行和注释。
为了把这一路的坑、血和泪都留个纪念,也为了期末 Blog 不再被老师挑“空洞”,我决定老老实实写一篇超 3000 字的复盘。
如果你正卡在 V1、V2 的重构里,不妨看看我的踩坑清单,也许能少走几步弯路——当然,也可能笑出声。
2 设计与分析|我的三版类设计到底改了什么?
有一说一, 这部分还是好设计的,那个调度算法是真阴间
2.1 V1(题目集 5):单类 —— 能跑但不好改
| 类 | 位置 | |||
|---|---|---|---|---|
dianti |
dt1.java |
|||
currentFloor |
||||
direction (enum) |
||||
| 两条数组队列 | dianti_run() (269 行,复杂度 7,最深嵌套 6) |
|||
should_setDirection() |
||||
is_need_stop() |
纯过程式写法,SRP 失守。 |
总结:V1 的问题不是“写不出来”,而是“改一行炸一片”。第一次提交后我就意识到:再加新需求一定会崩。
2.2 V2(题目集 6):第一次拆类,把职责拉出来透气

| 类 | 为什么需要它 | 跟谁交互 | 设计取舍 |
|---|---|---|---|
Elevator |
单纯保存电梯物理状态 | Controller |
只提供 getter/setter,不做逻辑 |
Controller |
大脑:决策 + 调度 | Elevator、RequestQueue |
仍然比较胖,复杂度 5,但比原来好 |
RequestQueue |
管两个链表 | Controller |
选 LinkedList 而不是数组,弹性好 |
InternalQuest / ExternalQuest |
把“请求”升级为对象 | RequestQueue |
方便以后加字段,如时间戳 |
2.3 V3(题目集 7)

| 角度 | 说明 |
|---|---|
| 架构设计 | 新增 Passenger 类:外部请求改为“源楼层 + 目的楼层”,停靠后自动将目的楼层加入内部队列,代码更贴近现实。 |
| 调度算法 | 流程:① 选取最近的同向请求 → ② 停靠源楼层接客 → ③ 将目的楼层加入内部队列 → ④ 继续运行。核心逻辑简化为 15 行以内。 |
| 性能指标 | 行数 530,最大圈复杂度 4,平均方法长度 9 行;PTA 用时缩短到 128 ms,功能更丰富反而更高效。 |
2.4 最终版本代码的 SourceMonitor 报表解读
下面是项目最新版在 SourceMonitor 中的统计截图:

| 字段 | 数值 | 解读 |
|---|---|---|
| Lines | 482 | 文件行数接近 500,说明 Main.java 已经承载了较多逻辑,需要考虑拆分。 |
| Statements | 216 | 业务语句较多,但与文件行数对比,空行与注释占比极低,代码密度较大。 |
| Percent Branch Statements | 17.6 % | 分支占比接近 20 %,整体逻辑尚可,但过深的分支会影响可读性。 |
| Method Call Statements | 95 | 方法调用占比高,说明跨类调用频繁,可关注接口设计是否合理。 |
| Percent Lines with Comments | 0.4 % | 注释极少,接近空缺,后期维护时几乎没有说明,需要大幅补充注释。 |
| Classes and Interfaces | 12 | 文件中包含 12 个类或接口,职责高度聚集,已超常规单文件管理范围。 |
| Methods per Class | 3.50 | 平均每类 3–4 个方法,单个文件内方法数量合理,但类数量过多建议分包。 |
| Average Statements per Method | 3.45 | 每方法平均 3–4 行语句,方法本身较短,但多方法堆叠导致文件过长。 |
| Name of Most Complex Method | Controller.recept_twoList() | 最复杂的方法负责读取并解析输入,逻辑集中,建议提取子方法简化。 |
| Maximum Complexity | 20 | 圈复杂度已超过 10 警戒线,位于 recept_twoList(),最急需拆分或优化。 |
| Maximum Block Depth | 8 | 嵌套深度高达 8 层,阅读与测试压力都很大,应考虑早返回和函数拆分。 |
| Average Block Depth | 2.39 | 平均嵌套深度合格,但高峰深度过高,说明少数方法极度临界。 |
改进思路:
- 将
Controller.recept_twoList()中的输入解析分解成多个私有方法,如parseExternal()、parseInternal();- 对过深的
if-else结构使用早期返回 (return),减少嵌套层级;- 增加注释,目标达到 10 % 以上,让后续阅读更轻松;
- 考虑将 Main.java 按包或功能拆分成多个文件,降低单文件复杂度。
3. 采坑清单|从 0 分到 100 分的“死因检讨”. 采坑清单|从 0 分到 100 分的“死因检讨”
| 坑号 | 报错关键词 | 真相 | 补救 | 花费时间 | |
|---|---|---|---|---|---|
| 01 | 非零返回 | 输入流错位 | 把 nextLine() 提前消费换行 |
15 min | |
| 02 | 运行超时 | 循环里狂 println |
限制打印频率 | 2 h | |
| 03 | 数组越界 | 自写队列指针乱跳 | 换 LinkedList |
一晚上 | |
| 04 | 死循环 | 重复请求未过滤 | 记录 lastFloor+lastDir |
30 min | |
| 05 | 目的楼层丢失 | 没把外部票拆两次 | Passenger 入内部队列 |
40 min |
血泪教训:打印永远别写在最深的循环里;队列逻辑一旦自实现,十有八九踩坑。
4 改进与展望(简版)
下面列的是我能想到、又觉得自己真有希望做到的几件事,用最直白的话写:
-
把“选下一层”的规则单独写成一个方法
以后如果想换别的算法(比如先到最近楼层、或者先到人最多的楼层),只改这一个地方,不用满文件找判断语句。 -
换掉死循环
现在电梯一直while(true)轮着看队列。 -
加日志文件
再也不用到处println。调试时开 DEBUG,正式跑只保留关键信息,出问题再翻日志。 -
补测试
现在覆盖率大概 40 %。目标是把常见情况和边界情况都写成 JUnit 用例,让覆盖率先到 70 %。有了测试,重构时心里更踏实。 -
友好的错误提示
以前读到非法输入直接continue,用户不知道哪错了。想改成提示“楼层超范围”或“格式错误”之类的信息,便于定位。
先把这 5 件事做好,再说更多花哨的功能。
5 写在最后|几个很朴素的想法 写在最后|几个很朴素的想法
这一段不讲术语,只说直白的感受。
5.1 这三周我真正记住的
- 拆分真的能救命。V1 全写在一个类里,后来想加一行都怕崩;分开之后虽然文件多了,但心里没那么慌。
- 打印≠日志。一开始用
System.out.println满屏飞,PTA 直接超时;学会分类输出后才发现“少说话”能提速。 - 测试不是走过场。写一两个样例远远不够,自己随便造 20 组数据才能找到边界 Bug。
- 数字会说话。SourceMonitor 的红条、PTA 的耗时,一眼就能看出问题在哪,比“感觉代码太乱”要准确得多。
5.2 目前最头疼的
- 注释当初写太少了,现在会头看代码有些方法得想一下才能想起来是干嘛的
- Jacoco 只有 40 多 %,说明还有很多路径没跑到;
5.3 给课程组的一点小建议
- 测试点分层:能不能先跑基础用例、再跑高难度用例?而且把测试点分开来.这样定位问题更快。
- 示例代码分享:如果能在课堂或邮件里提供一份官方参考实现,大家就可以边看边学,明白出题的思路。
- 实时答疑时间:作业发布后隔几天安排一次线上答疑,针对同学的具体问题进行讲解,能大大减少走弯路的时间。
5.4 接下来的小目标
- 深入学习java程序设计实现
- 学习一波计算机互联网原理
- 每月写一篇博客记录踩坑,逼自己输出。
尾声:电梯项目暂时告一段落,代码还有很多不完美,但能清楚地看到自己从“能跑”到“敢改”的变化——这就够了。
浙公网安备 33010602011771号