电梯调度迭代编程作业复盘:从问题剖析到能力进阶
一、对三次电梯调度题目集的整体认知
(一)知识点覆盖与考察重点
三次电梯调度题目集聚焦面向对象编程核心知识点与工程化开发能力,核心考察内容可归纳为三类:
设计原则:核心是单一职责原则(SRP)。从第一次的 “单类包揽所有逻辑”,到第二次拆分出电梯类、请求队列类、控制类,再到第三次取消请求类并新增乘客类,本质是要求开发者明确 “一个类只负责一个功能模块”,避免职责耦合。这要求开发者能准确识别程序中的功能模块,并为每个模块设计对应的类结构。
数据结构的实际应用:以队列为核心数据结构,管理电梯内部请求与外部请求,考察队列的入队、出队、判空、去重等操作的实现,以及如何通过队列保障请求处理的有序性。
调度算法的逻辑实现:核心是 “电梯优先处理同方向请求,顺路停靠” 的调度规则,考察对业务逻辑的抽象能力与代码转化能力,包括方向判断、请求匹配、电梯状态切换等关键逻辑的实现。
输入输出的处理:要求解析不同格式的请求(内部请求为单一楼层、外部请求为源楼层 + 目的楼层),过滤无效请求(如超范围楼层、非数字输入)与重复请求(连续相同的请求),考察对异常输入的处理能力与字符串解析能力。
(二)难度递进与挑战点
三次作业的难度呈阶梯式上升,每一次迭代都在原有基础上增加了新的技术要求:
第一次作业:核心是实现基础的电梯调度逻辑,只需设计一个电梯类,包含状态管理(当前楼层、运行方向、运行状态)与简单的调度算法(处理内部、外部请求)。但此时我已暴露出对 “状态与逻辑分离” 的认知不足,将输入解析、调度算法、状态管理全部塞在一个类中,代码臃肿且难以维护。
类图设计:

Main类:使用正则表达式来正确读取每行输入当中所需的数据,然后按数据的形式来进行外部或者内部的请求的加入。
Elevator类:该类与外部请求类相关联,主要用来控制电梯的运行,和方向的确定,以及打印电梯当前所在的楼层、状态和运行方向。
Source Monitor分析结果:

1.代码复杂度为2,阅读性高
2.注释太少,导致做第二次作业时花了大量时间去思考第一次的思路,但是还是没有完成第二次作业
第二次作业:核心挑战是类的拆分与职责划分,要求将原有单类拆分为电梯类、请求队列类、控制类,同时新增 “过滤连续重复请求” 的需求。此时我对 “单一职责原则” 的理解仅停留在 “拆分类” 的表面,未能明确每个类的核心职责(如队列类应只负责请求的存储与操作,控制类负责调度逻辑),导致类之间的调用关系混乱,程序报错频发。
类图设计:

Source Monitor分析结果:

1.代码复杂度为7,原因应该是嵌套循环太多,影响了代码的性能
第三次作业:难度进一步提升,要求新增乘客类并取消请求类,同时修改外部请求格式为 “源楼层 + 目的楼层”,并实现 “外部请求处理后将目的楼层加入内部队列” 的逻辑。这一步需要重新整合请求的封装逻辑,且调度算法需适配新的请求格式,我因前两次的基础薄弱,无法快速调整类结构与逻辑,最终程序陷入 “解析请求失败 — 调度逻辑混乱 — 无输出” 的恶性循环,最终没有完成。
类图设计:

二、开发过程中的核心问题剖析
自身在面向对象认知、逻辑实现、调试能力等方面存在显著短板,具体问题可归纳为以下四类:
(一)类设计的认知偏差:对单一职责原则的理解与落地不足
单一职责原则是本次作业的核心考察点,但我在开发中始终未能准确把握 “职责划分” 的本质,这是导致程序结构混乱的根源。
第一次作业的 “大一统” 思维:最初编写代码时,我认为 “电梯调度逻辑简单,无需拆分类”,于是将所有功能都封装在Elevator类中:包括电梯的状态变量(当前楼层、方向、状态)、请求队列的存储(用List直接存储请求)、输入解析方法(parseInput)、调度算法方法(dispatch)、电梯动作方法(moveUp、openDoor)等。整个类的代码量超过 500 行,变量与方法交织,一旦出现问题(如调度逻辑错误),很难定位具体是哪个模块的问题。例如,当电梯出现 “不处理外部请求” 的问题时,我既需要检查输入解析是否正确,又要排查调度算法是否遗漏了外部请求的判断,还需确认队列是否正确存储了请求,调试效率极低。
第二次作业的 “形式化拆分”:第二次作业要求拆分出队列类、控制类,我虽按要求创建了RequestQueue和ElevatorController类,但并未真正实现职责分离。例如,我将 “请求去重” 的逻辑写在了Elevator类中,而非RequestQueue类 —— 队列类本应负责请求的存储与去重,却被简化为仅包含enqueue和dequeue的空壳;控制类本应负责核心调度,却又夹杂了输入解析的代码。这种 “形式上拆分类,本质上职责仍耦合” 的做法,导致程序出现新的错误:比如队列类的去重逻辑缺失,导致重复请求未被过滤;控制类调用电梯类的方法时出现空指针异常,因为类之间的依赖关系未梳理清晰。
第三次作业的 “类结构重构失败”:第三次作业要求新增Passenger类并取消请求类,我未能理解 “用乘客类封装请求信息” 的设计意图,仍沿用第二次的请求存储逻辑(用String存储请求),导致外部请求的 “源楼层” 与 “目的楼层” 无法被正确解析和封装。例如,解析外部请求<1,3>时,我仍将其作为字符串存储,而非创建Passenger对象存储源楼层 1 和目的楼层 3,后续调度算法无法获取目的楼层,自然无法将其加入内部队列,最终导致电梯处理完外部请求后无后续动作。
(二)调度算法的逻辑漏洞:对核心业务规则的实现偏差
电梯调度的核心规则是 “优先处理同方向请求,顺路停靠”,但我在实现这一规则时,因逻辑思考不严谨,出现多处关键漏洞,导致电梯运行不符合预期。
同方向请求判断的逻辑错误:我对 “同方向请求” 的判断条件设计错误,最初的代码中,仅判断 “当前请求的楼层是否在电梯运行方向上”,而非 “队列中是否存在同方向的请求”。例如,电梯当前在 3 层,方向为上行,内部队列中有 5 层的请求,外部队列中有 4 层的上行请求,我的代码会先处理 5 层的请求,却忽略了 4 层的顺路请求,导致电梯直接从 3 层到 5 层,跳过了 4 层的外部请求。这一错误的根源是我未遍历队列中的所有请求,仅判断了队首请求的方向,违背了 “顺路停靠” 的规则。
外部请求转内部请求的逻辑遗漏:第三次作业要求 “处理完外部请求后,将目的楼层加入内部队列”,我在代码中完全遗漏了这一逻辑。例如,乘客在 1 层发起外部请求<1,3>,电梯到达 1 层处理该请求后,未将 3 层加入内部队列,导致电梯停在 1 层无后续动作,程序陷入停滞。这一问题暴露了我对业务规则的理解不全面 —— 只关注了 “处理外部请求的源楼层”,却忽略了 “乘客进入电梯后会按下目的楼层” 的实际场景。
电梯方向切换的死循环问题:当同方向请求处理完毕后,我的代码会直接切换为反方向,却未判断反方向是否存在请求,导致电梯陷入 “上行 — 下行 — 上行” 的死循环。例如,电梯处理完所有上行请求后,方向切换为下行,但此时无任何下行请求,代码仍会执行moveDown方法,导致电梯从最高层一直下降到最低层,且中途无任何停靠,完全偏离了调度规则。
(三)输入处理的细节缺陷:对异常输入与请求过滤的处理粗糙
输入处理是程序运行的 “入口”,但我在这一环节的代码编写过于低级,导致大量无效输入未被过滤,程序易出现崩溃或逻辑错误。
异常输入的过滤不全面:作业要求过滤 “超出楼层范围的请求” 和 “非数字输入”,但我的代码仅对楼层范围做了简单判断,未处理非数字输入的情况。例如,当输入<a,3>或<2,DOWN>(第三次作业已修改请求格式,此处为第二次作业的错误)时,程序会因Integer.parseInt()抛出NumberFormatException而崩溃;当输入<10,5>(10 超出最大楼层 5)时,代码虽能过滤该请求,但未给出任何提示,导致我误以为请求已被正确处理,后续调试时花费大量时间寻找 “电梯为何不处理该请求” 的原因。
重复请求的过滤逻辑错误:第二次作业要求 “过滤连续的相同请求”,我却实现了 “过滤所有相同请求” 的逻辑。例如,输入<3>→<2>→<3>时,我的代码会过滤最后一个<3>请求,而根据题目要求,只有连续的<3>→<3>才需要过滤。这一错误的根源是我未理解 “连续重复” 的定义,仅通过List.contains()判断队列中是否已有该请求,而非记录上一个请求并判断是否与当前请求相同。
(四)调试能力的不足:缺乏科学的问题定位方法
当程序出现错误时,我盲目修改代码,导致问题越改越多,最终陷入僵局。
未使用断点调试:我对 IDEA 的断点调试功能不熟悉,仅通过System.out.println()打印少量信息,且打印的内容缺乏针对性。例如,当电梯无输出时,我仅打印 “电梯开始运行”,却未打印电梯的当前楼层、方向、队列中的请求数量,无法判断是输入解析失败导致队列为空,还是调度算法未执行。
未梳理程序运行流程:遇到问题时,我未先手动梳理程序的运行流程,而是直接修改代码。例如,当电梯出现死循环时,我未先画流程图分析 “方向切换 — 请求判断 — 电梯移动” 的逻辑链,而是随意修改方向切换的条件,导致死循环问题未解决,又新增了 “电梯不移动” 的问题。
三、开发过程中的心路历程:从轻视到困惑,再到挫败与反思
本次电梯调度作业的开发过程让我深刻认识到自身的能力短板。
(一)初始阶段:轻视题目,盲目动手
第一次看到电梯调度的题目时,我觉得 “电梯调度是日常场景,逻辑应该很简单”,于是未做任何准备就直接动手写代码。我先在纸上简单写了几个变量(currentFloor、direction)和方法(moveUp、openDoor),便开始在 IDEA 中编写代码,完全忽略了类设计的重要性。此时的我认为 “功能实现比代码结构更重要”,只要电梯能运行并处理请求即可,却不知这种 “重功能、轻结构” 的做法为后续的迭代开发埋下了巨大隐患。当第一次作业的代码写完后,虽然能处理简单的内部请求,但面对外部请求时,程序频繁出错,我才意识到 “代码结构混乱” 会导致问题难以解决。
(二)第二次迭代:困惑不解,尝试补救
第二次作业要求拆分类结构并处理请求去重,我开始感到困惑:“为什么要拆分类?一个类不是也能实现功能吗?” 我查阅了单一职责原则的资料,但仅理解了 “一个类只做一件事” 的字面意思,无法落地到实际代码中。我尝试参考同学的类结构,创建了RequestQueue和ElevatorController类,但因不理解每个类的职责,只能照猫画虎地写方法,导致类之间的调用关系混乱。例如,我在控制类中创建了电梯类的对象,又在电梯类中创建了队列类的对象,形成了循环依赖,程序启动时就抛出空指针异常。此时我也曾向同学请教,同学指出 “队列类应独立负责请求管理,控制类负责调度,电梯类负责状态管理”,但我因基础薄弱,无法快速调整代码结构,只能在原有错误的基础上修修补补,最终第二次作业的代码仍未能通过基础测试点。
(三)第三次迭代:无助迷茫,难以推进
第三次作业的要求让我陷入了更深的迷茫:新增乘客类、修改外部请求格式、实现外部请求转内部请求的逻辑,这些要求需要对原有代码进行大规模重构,而我连第二次的代码都未理顺,重构更是无从下手。我尝试先修改输入解析的代码,将外部请求解析为乘客对象,但因对Object类的转型、队列的泛型使用不熟悉,始终无法将乘客对象正确存入队列。例如,我用LinkedList
浙公网安备 33010602011771号