一、前言
本次共完成三次题目集训练,核心围绕 “单部电梯调度程序” 的迭代开发展开,辅以基础语法与逻辑验证类题目,整体呈现递进式训练节奏。以下从知识点覆盖、题量分布与难度梯度三方面进行总结:
(一)知识点覆盖
三次题目集始终以 “面向对象编程(OOP)” 为核心,逐步扩展知识边界:
题目集 1:聚焦基础语法与单一类功能实现,涉及LinkedList队列操作、正则表达式(Pattern/Matcher)请求解析、分支与循环逻辑控制,核心目标是让开发者掌握 “需求转化为代码” 的基本能力,理解电梯调度的核心规则(同向优先、逐层移动、状态切换)。
题目集 2:引入 “单一职责原则(SRP)”,要求拆分类职责,新增enum枚举(Direction/State)管理电梯方向与状态、ExternalRequest类封装外部请求,同时涉及请求去重逻辑(连续重复请求过滤)与类间协作(电梯类 - 队列类 - 控制类的交互),重点训练类设计与模块化思维。
题目集 3:优化数据模型,取消独立请求类,新增Passenger类封装乘客属性(源楼层、目的楼层),外部请求格式从 “楼层 + 方向” 改为 “源楼层 + 目的楼层”,并新增 “外部请求处理后自动转为内部请求” 的业务逻辑,进一步贴近真实电梯场景,同时强化类间依赖管理与业务流程衔接。
(二)题量与难度分布
三次题目集均以 “单部电梯调度程序” 为核心,难度呈上升:
题目集 1:测试点只有一个占了题目集的70分,在判断电梯移动方向理解上有问题,核心挑战在于 “正确解析请求格式” 与 “实现同向优先调度逻辑”。
题目集 2:在上一个的基础上进行了 “类职责拆分” 与 “请求去重”。
题目集 3:在前两个的基础上修改,请求封装成了乘客请求,对外部请求的格式和处理进行了改进,应该是功能具体实现上漏写了什么情况,导致一个测试点没过。
二、设计与分析
(一)题目集 1:单一类架构与基础调度实现
- 架构设计
采用 “少类多职责” 的简化设计,核心类仅 3 个:RequestNode(请求数据封装)、RequestQueue(请求存储与管理)、Elevator(核心调度逻辑),Main类负责输入输出与初始化。整体架构无明确的模块划分,Elevator类承担了 “请求解析”“状态管理”“调度算法”“输出控制” 四大核心职责,类间依赖关系简单但耦合度极高(Elevator直接操作RequestQueue的内部队列)。
类图如下:

- 核心逻辑分析
请求解析与存储:通过两个正则表达式分别匹配内部请求(^<(\\d+)>$)与外部请求(^<(\\d+),\\s*(UP|DOWN)\\s*>$),解析后通过RequestQueue的addNode方法加入队列,仅在添加时判断楼层有效性与当前楼层重复性,未对非数字格式请求进行严格过滤,存在 “无效数据进入队列” 的潜在风险。
调度算法:采用 “同向优先 + 输入顺序” 的调度策略,通过findSameDirByInputOrder方法遍历队列,查找当前方向上首个符合条件的请求(UP 方向找大于当前楼层的请求,DOWN 方向找小于当前楼层的请求);无同向请求时立即切换方向,仍无则匹配任意状态符合的请求。该算法实现简单,但未考虑请求与当前楼层的距离,可能导致 “绕路” 问题(如当前楼层 5,存在请求 3(UP)与 7(UP),按输入顺序先处理 3 再处理 7,多移动 4 层)。
状态管理与停站处理:电梯状态通过 “是否有请求” 与 “当前楼层是否等于目标楼层” 间接判断,无明确的State枚举;到达目标楼层后,根据队列大小判断处理逻辑 —— 若仅剩最后一个请求,同时移除该楼层的所有类型请求(UP/DOWN/DES),否则按 “同向外部请求优先,内部请求次之” 的顺序处理
- 性能与架构评估:基于 SourceMonitor 的量化分析

通过 SourceMonitor 对题目集 1 的源码进行性能与复杂度分析,
方法复杂度:
Elevator.parseAndAddRequest()方法复杂度达 9,远超 “单个方法≤7” 的基准,原因是该方法同时承担 “请求格式校验、数字解析、楼层合法性判断、队列添加” 四类逻辑,包含if-else嵌套(如正则匹配→数字校验→楼层范围判断),导致分支过多;
块深度:
最大块深度达 5(如Elevator.run()方法中 “移动逻辑→停站判断→请求处理” 的三层嵌套),代码层级深,调试时需逐层定位;
代码规模:
代码行数仅 284 行,但类数仅 2 个(Elevator/RequestQueue),单个类平均承担 142 行代码,Elevator类同时负责 “调度、状态管理、请求解析”
(二)题目集 2:单一职责拆分与模块化优化
1.架构设计
针对题目集 1 的架构缺陷,题目集 2 按照 “单一职责原则” 对类结构进行彻底拆分,核心类增至 5 个(含 2 个枚举类),形成 “数据封装 - 队列管理 - 调度控制 - 入口初始化” 的清晰模块划分:
Direction/State(枚举类):分别管理电梯运行方向(UP/DOWN/IDLE)与运行状态(MOVING/STOPPED),替代题目集 1 中的字符串常量,提升类型安全性与代码可读性。
ExternalRequest(数据封装类):专门封装外部请求的属性(楼层 + 方向),重写equals方法用于请求去重,实现数据与行为的绑定。
Elevator(电梯实体类):仅管理电梯自身属性(当前楼层、方向、状态、楼层范围),提供属性访问器(getter/setter)与基础工具方法(isValidFloor),不参与调度逻辑,实现 “状态与行为分离”。
RequestQueue(请求管理类):负责请求解析、去重、存储与查询,区分内部请求队列与外部请求队列,通过接口方法(findSameDirTarget/removeFirstInternalRequest)隐藏内部数据结构,实现 “数据封装与隔离”。
Controller(调度控制类):核心调度模块,通过协调Elevator与RequestQueue的交互,实现方向判断、移动控制、停站处理等核心逻辑,承担 “大脑决策” 角色。
Main(入口类):仅负责输入读取、组件初始化与调度启动,不参与业务逻辑,实现 “入口与核心逻辑分离”。
类图如下:

2.核心逻辑优化
请求去重逻辑:内部请求通过 “判断当前请求与队尾请求的楼层是否一致” 实现去重;外部请求通过重写ExternalRequest的equals方法,同时比较 “楼层 + 方向” 实现精准去重,解决了题目集 1 中 “连续相同请求重复处理” 的问题。例如输入<3,UP>三次,队列仅保留 1 个有效请求,提升了调度效率。
方向确定算法:Controller的determineDirection方法采用 “常规逻辑 + 兜底逻辑” 的分层策略:
常规逻辑 1:若当前方向有同向请求,保持方向不变;
常规逻辑 2:若当前方向无请求,切换至反向检查,有则切换方向;
初始逻辑:若电梯处于 IDLE 状态,优先尝试 UP 方向,再尝试 DOWN 方向;
兜底逻辑:若所有常规方向无目标但仍有请求,强制前往剩余请求楼层。该策略确保了方向判断的全面性,避免了 “请求遗漏” 或 “方向频繁切换” 的问题。
状态管理与移动控制:通过State枚举明确电梯状态,move方法触发时设置状态为MOVING,开门时切换为STOPPED,状态切换可追溯;移动逻辑采用 “一层一步” 模式,每次移动后检查是否需要停站,确保 “顺路请求不遗漏”。
3.性能与架构评估:量化指标的显著改善

通过 SourceMonitor 对题目集 2 的源码进行分析,
方法复杂度:
题目集 2 拆分出RequestQueue类后,RequestQueue.getQueueInstance()方法复杂度降至 6,仅负责 “请求解析” 单一逻辑;
块深度:
最大块深度5,平均块深度在1.16。
规模:
题目集 2 类数增至 5 个(新增Controller/ExternalRequest/ 枚举类),代码行数升至 438 行,但单个类平均代码行数降至 87.6 行,职责更聚焦(如Controller仅负责调度);
(三)题目集 3:乘客模型引入与真实场景适配
1.架构设计
题目集 3 在题目集 2 的模块化架构基础上,优化了数据模型设计,核心变化是 “取消独立请求类,引入统一乘客类(Passenger)”,实现了 “请求数据” 到 “用户实体” 的映射,让程序设计更贴近真实电梯运行场景。核心类结构保持 “电梯类 - 队列类 - 控制类 - 入口类” 的四大模块,但数据流转逻辑发生显著变化:
Passenger(核心数据模型类):统一封装内部乘客与外部乘客的属性,内部乘客仅包含 “目的楼层”(sourceFloor为 null),外部乘客包含 “源楼层” 与 “目的楼层”,提供getDirection方法自动计算乘梯方向(源楼层 < 目的楼层为 UP,反之为 DOWN),替代了题目集 2 中ExternalRequest的方向属性。
RequestQueue(请求管理类):队列存储对象从 “请求” 改为 “乘客”,区分内部乘客队列与外部乘客队列,新增 “外部乘客转内部乘客” 的逻辑(外部乘客被接走后,其目的楼层自动加入内部队列),实现 “接客 - 送客” 的流程闭环。
Controller(调度控制类):优化调度算法,新增findTargetFloor方法,通过 “当前方向最近目标 + 全局最近目标” 的双层判断,选择最优移动目标,减少无效移动;moveToTarget方法支持 “中途停站处理”,解决了题目集 2 中 “仅处理队头请求,顺路请求遗漏” 的问题。
类图如下:

2.核心逻辑
乘客模型的统一封装:Passenger类通过两个构造方法分别适配内部请求(仅目的楼层)与外部请求(源楼层 + 目的楼层),统一了数据格式,避免了题目集 2 中 “内部请求为 Integer 类型,外部请求为对象类型” 的不一致问题;getDirection方法自动计算方向,减少了请求解析时的方向判断逻辑,让外部请求格式从 “楼层 + 方向” 改为更贴近真实场景的 “源楼层 + 目的楼层”(如<5,9>表示 5 楼乘客要去 9 楼)。
外部请求的处理:当电梯到达外部乘客的源楼层并开门时,Controller的openDoorAndProcess方法会移除外部队列的该乘客,并将其目的楼层作为内部请求加入内部队列,模拟了 “乘客进梯后按下目的楼层” 的真实操作。例如外部请求<5,9>处理后,内部队列自动新增目的楼层 9 的请求。
调度算法的优化:findTargetFloor方法采用 “双层筛选” 策略:
第一层(同向最近):查找当前方向上,距离当前楼层最近的内 / 外部请求(内部请求看目的楼层,外部请求看源楼层);
第二层(全局最近):若当前方向无目标,计算所有内 / 外部请求与当前楼层的距离,选择最近目标。该算法解决了题目集 2 中 “按输入顺序调度导致的绕路问题”,例如当前楼层 5,内部请求 8、外部请求 10(UP 方向),优先处理 8 而非 10,减少了 2 层的无效移动。
- 性能与架构评估:场景适配后的指标优化

通过 SourceMonitor 对题目集 3的源码进行分析,
方法复杂度:
题目集 3 进一步优化调度逻辑,Controller.determineDirection()方法复杂度仅 5,通过 “同向请求判断→反向请求判断→兜底逻辑” 的分层设计,减少冗余分支。
块深度:
最大块深度4,平均块深度在1.25。
规模:
题目集 3 类数增至 7 个(新增Passenger类),代码行数降至 398 行,实现 “代码量减少 + 功能复杂度提升” 的平衡,证明模块化设计可减少冗余代码。
三、采坑心得
(一)题目集 1:基础逻辑与格式问题
1. 无效请求未过滤导致队列异常
问题描述:输入超范围楼层(如最小 1、最大 20,输入<25>)时,程序未过滤该请求,导致Elevator类在run方法中计算nextTarget时出现 “目标楼层超出范围”,进而引发无限循环(如当前楼层 20,目标楼层 25,currentFloor始终小于nextTarget,持续输出 UP 方向)。
解决方案:在Elevator的parseAndAddRequest方法中,新增 “楼层有效性判断”:调用isValidFloor方法检查楼层是否在[minFloor, maxFloor]范围内,同时排除 “当前楼层与请求楼层相同” 的无效请求,确保只有合法请求进入队列。
心得:在处理用户输入时,需对 “数据格式”“数据范围”“业务逻辑有效性” 进行三重校验,避免无效数据进入核心流程。
2. 同向优先逻辑理解有误
问题描述:同向优先逻辑理解有误,导致没有按要求移动,或者出现卡在一个楼层死循环上下走。
解决方案:同向优先” 规则:当前楼层4楼,方向UP,请求剩下是<3,UP>,<5,DOWN>,这时候没有符合UP,DOWN方向逻辑的,就只看方向标志,当前电梯方向为UP,那么就去同为UP的<3,UP>,DOWN到了之后为3,DOWN,去<5,DOWN>。注意处理到剩余请求有<3,UP>,<5,DOWN>时候内部请求已经没了,符合UP,DOWN要求的外部请求也没了,只剩下特殊情况。按照这个方向判断逻辑实现功能。
(二)题目集 2:类设计与去重逻辑问题
1. 类间耦合过高导致扩展困难
问题描述:Controller类直接访问RequestQueue的internalRequests与externalRequests属性(如queue.internalRequests.peek()),而非通过getInternalHeadFloor等接口方法,当RequestQueue修改内部数据结构(如将LinkedList改为ArrayList)时,Controller类需同步修改,违反 “开闭原则”。
解决方案:在RequestQueue中封装所有内部数据访问,提供getInternalHeadFloor(获取内部队头楼层)、getExternalHeadDirection(获取外部队头方向)等接口方法,Controller仅通过接口访问数据,不依赖具体实现。
心得:类间依赖应遵循 “依赖倒置原则”—— 依赖接口而非具体实现,通过封装内部数据降低耦合度,提升代码可扩展性。
(三)题目集 3:请求转换与调度算法问题
1. 调度算法未判断电梯移动方向有误导致与样例不符
问题描述:判断电梯移动方向逻辑有误导致与样例不符。
解决方案:应当遵循同方向最近楼层请求,处理队头;无同方向最近请求时,找距离当前楼层最近的楼层请求,例如:在7楼,当前方向UP,队头分别为<9,6>,<3>(外部请求处理后得到的目的请求放内部请求队尾,产生的<3>),去最近的<9,6>,因此继续向上走,而不是先向下,再向上。
四、改进建议
(一)题目集 1:优化无效请求过滤逻辑,解决 “无效数据引发的运行异常”
- 现存问题
题目集 1 的parseAndAddRequest方法仅对 “楼层范围” 和 “当前楼层重复性” 进行校验,未处理非数字格式请求(如<abc>)和空请求(如<>),导致无效数据进入RequestQueue,进而引发getNextTarget方法计算目标楼层时出现逻辑错误(如无限循环、空指针异常)。例如输入<25>(最大楼层 20)时,程序会持续输出 “Current Floor:20 Direction:UP”,无法终止。
- 具体优化方案
在Elevator类的parseAndAddRequest方法中,新增 “格式合法性 + 数据类型” 的双重校验逻辑,步骤如下:
格式预校验:在正则匹配前,先判断请求字符串是否符合 “<开头、>结尾” 的基础格式,若不符合直接忽略(如输入 “3,UP”“<3,up>” 等格式错误请求);
数字类型校验:解析楼层字符串时,用try-catch捕获NumberFormatException,非数字格式(如<abc>)直接忽略;
(二)题目集 2:引入 “接口抽象” 降低类间耦合,解决 “扩展困难” 问题
- 现存问题
题目集 2 中Controller类直接依赖RequestQueue和Elevator的具体实现(如queue.getInternalRequests().peek()),而非接口。
2. 具体优化方案
定义IRequestQueue和IElevator两个接口,封装核心操作方法,让RequestQueue和Elevator实现接口,Controller仅依赖接口而非具体类,实现 “依赖倒置”。
(三)题目集 3:
没改进建议,测试点有一个没过。
五、总结
(一)学习收获
熟练掌握了队列、正则表达式、枚举、类间协作等核心技术的应用,能够快速将业务需求转化为技术实现;
理解并实践了单一职责原则、依赖倒置原则、开闭原则等架构设计原则,能够设计 “高内聚、低耦合” 的模块化系统;
建立了 “需求拆解” 的工程化思维,能够将复杂业务规则(如电梯调度)拆解为可执行的模块与方法。
(二)需进一步学习的方向
当前仅初步应用了单一职责原则与观察者模式的思路,对工厂模式、策略模式、单例模式等的应用场景与实现方式理解不深,后续需系统学习设计模式,并在实际项目中实践,提升架构设计的灵活性。
(三)课程与教学改进建议
适当增加测试点;示范样例更体现题目核心逻辑。