电梯调度程序的三次作业分析

电梯调度程序的三次作业分析

目录

  1. 前言
    1.1 关于知识点
    1.2 关于难度
  2. 设计与分析
    2.1 第一次作业:基础架构搭建
    2.1.1 我的设计
    2.1.2 我的分析
    2.2 第二次作业:优化重复请求处理
    2.2.1 我的设计(在第一次基础上的增加与改变)
    2.2.2 我的分析
    2.3 第三次作业:重构请求模型与逻辑衔接
    2.3.1 我的设计
    2.3.2 我的分析
  3. 踩坑心得
    3.1 第一次作业
    3.2 第二次作业
    3.3 第三次作业
  4. 改进建议
  5. 总结

前言

1. 关于知识点

三次电梯调度程序作业围绕Java面向对象编程与实际业务逻辑实现展开,串联了多个核心知识点:

  • 基础语法与面向对象设计:类的封装、属性与方法定义、对象实例化,三次作业中逐步完善Elevator类结构,并新增Passenger类,体现了“数据与行为绑定”的面向对象思想。
  • 集合框架应用:核心使用Queue接口(LinkedList实现)管理请求队列,利用队列“先进先出”特性保证请求处理的顺序性,第二次作业中还涉及队列元素的遍历与去重操作。
  • 输入输出处理:使用BufferedReader读取多行输入,解析不同格式的请求字符串(区分内部/外部请求、处理格式校验与异常捕获),直到“end”终止输入。
  • 业务逻辑建模:将“同方向优先”“逐楼层停靠”“请求转换”等实际电梯运行规则,转化为可执行的代码逻辑,实现业务需求与技术实现的映射。

2. 关于难度

三次作业呈现明显的递进式难度曲线:

  • 第一次作业:难度中等,核心是搭建基础架构。需准确理解电梯的核心属性与运行规则,重点解决“内部/外部请求区分”“同方向优先处理”“逐楼层停靠检查”等基础问题,难点在于方向决策逻辑的初步实现(避免电梯频繁变向)。
  • 第二次作业:难度稍增,属于“优化型迭代”。在第一次架构基础上,需新增“重复请求去除”功能,难点在于明确“重复”的判定标准(内部请求看楼层,外部请求看“楼层+方向”组合),同时避免遍历队列时的并发问题与逻辑冗余。
  • 第三次作业:难度较高,属于“重构型迭代”。需新增Passenger类封装完整出行信息,修改外部请求输入格式,核心难点在于“外部请求处理后转换为内部请求”的逻辑衔接,以及方向决策逻辑适配Passenger类的属性迁移(从直接读取方向参数改为通过源/目的楼层推导),同时要兼容前两次作业的去重逻辑与运行规则。

设计与分析

第一次作业:基础架构搭建

我的设计

  1. 类结构设计:
    • 定义OuterRequest类封装外部请求,包含“请求楼层”和“乘梯方向”两个核心属性,区分上行(UP)与下行(DOWN)请求。
    • 定义Elevator类,核心属性包括最小/最大楼层、当前楼层、运行方向(默认向上)、内部请求队列(Queue<Integer>,存储电梯内乘客的目标楼层)、外部请求队列(Queue<OuterRequest>,存储电梯外乘客的呼叫请求)。
    • 核心方法LiftProcess()实现电梯运行主逻辑,getDirection()实现方向决策逻辑。
  2. 输入解析:
    • 读取前两行输入作为最小/最大楼层,后续行按<楼层数>(内部请求)或<楼层数,方向>(外部请求)格式解析,忽略无效格式与超出楼层范围的请求,直到“end”终止。
  3. 运行逻辑:
    • 电梯初始位于1楼、方向向上,只要存在未处理请求则持续运行。
    • 逐楼层移动,每次移动后检查当前楼层是否有匹配请求(内部请求直接匹配楼层,外部请求需匹配楼层+方向)。
    • 若有匹配请求,执行“开门-处理请求-关门”流程,同方向请求优先处理,全部处理完毕后再切换方向。

我的分析

第一次作业的核心是“搭建稳定的基础框架”,关键设计思路如下:

  • 用专门的OuterRequest类封装外部请求,避免直接使用字符串或零散变量存储请求信息,提升代码可读性与维护性。
  • 选择Queue存储请求,符合“先发起的请求先处理”的实际业务场景,避免请求混乱。
  • 方向决策逻辑是核心难点:通过判断当前未处理的内部/外部请求与当前楼层的位置关系,确定电梯是否保持原方向或切换方向,确保“同方向优先”规则的落地。
  • 逐楼层移动+实时检查请求的设计,贴合电梯实际运行逻辑,能准确处理“中途停靠”场景,但需注意避免遗漏请求或重复处理。
    第一次

第二次作业:优化重复请求处理

我的设计

image

  1. 核心新增功能:请求去重逻辑,在将请求加入队列前,先判断队列中是否已存在相同请求,避免重复处理。
    • 内部请求去重:遍历内部请求队列,若已存在相同楼层,则不重复添加。
    • 外部请求去重:遍历外部请求队列,若已存在“相同楼层+相同方向”的请求,则不重复添加(同一楼层的上行与下行请求视为不同请求)。
  2. 代码调整:
    • 在输入解析后、添加请求到队列前,新增去重校验方法(isInnerRequestDuplicate()isOuterRequestDuplicate())。
    • 保持Elevator类核心结构、运行逻辑与第一次作业一致,仅在请求入队环节增加过滤步骤。

我的分析

第二次作业的核心是“优化用户体验与运行效率”:

  • 重复请求的存在会导致电梯无效停靠(比如同一楼层多次呼叫上行),增加运行时间,去重设计能有效解决该问题,让程序更贴近实际电梯的运行逻辑。
  • 去重的关键是明确“重复判定维度”:内部请求仅需判断楼层,外部请求需结合“楼层+方向”,因为同一楼层可能同时存在上行和下行两种不同需求,不能简单按楼层去重。
  • 去重逻辑需在“请求入队前”执行,避免队列中积累无效请求,同时要注意遍历队列时的效率(若请求量较大,可考虑用HashSet辅助存储已存在的请求特征,提升查询速度)。
  • 该次优化属于“增量改进”,未改变核心架构,体现了迭代开发中“先稳定后优化”的思路。
    第二次

第三次作业:重构请求模型与逻辑衔接

我的设计

image

  1. 核心重构与新增:
    • 新增Passenger类,封装“请求源楼层”和“请求目的楼层”,通过getDirection()方法自动推导乘梯方向(目的楼层>源楼层为UP,反之则为DOWN),替代原OuterRequest类。
    • 调整Elevator类属性:外部请求队列改为Queue<Passenger>,存储完整的乘客出行信息。
    • 新增请求转换逻辑:外部请求处理(乘客上车)后,将其“目的楼层”添加到内部请求队列尾部,实现“乘车-到达目的地”的完整流程。
  2. 输入解析调整:
    • 外部请求格式从<楼层数,方向>改为<源楼层,目的楼层>,解析时需校验源楼层≠目的楼层、楼层在有效范围,否则视为无效请求。
    • 内部请求格式保持<楼层数>不变,继续沿用第二次作业的去重逻辑。
  3. 运行逻辑适配:
    • 方向决策逻辑适配Passenger类:外部请求的方向不再通过输入参数获取,而是调用Passenger.getDirection()推导。
    • 处理外部请求时,除了将请求出队,还需将乘客的目的楼层加入内部队列(同时执行去重),确保乘客能到达目的地。

我的分析

第三次作业的核心是“模型重构与业务逻辑闭环”:

  • Passenger类的引入是关键改进,将分散的“请求楼层”“方向”“目的楼层”整合为完整的乘客出行实体,更符合现实场景(乘客的核心需求是从A楼到B楼,方向是衍生属性),也减少了输入格式错误(无需手动输入UP/DOWN,避免大小写错误)。
  • 外部请求转内部请求的逻辑,实现了“呼叫电梯-上车-到达目的地”的业务闭环,让程序从“处理孤立请求”升级为“服务完整出行需求”,更具实用性。
  • 重构过程中需注意兼容性:需保留前两次作业的“同方向优先”“逐楼层停靠”“去重”等核心规则,仅修改请求模型与输入解析逻辑,避免核心功能退化。
  • 方向决策逻辑的适配是难点:需将原依赖OuterRequest.direction的代码,改为从Passenger类推导方向,确保“同方向优先”规则不受影响。
    第三次

踩坑心得

第一次作业

  1. 外部请求方向判断失误:初期未区分“外部请求的方向”与“电梯当前方向”的匹配逻辑,导致电梯在下行时处理了同一楼层的上行请求,违反“同方向优先”规则。后来通过在处理外部请求时增加“当前电梯方向==请求方向”的判断条件,解决该问题。
  2. 楼层转换逻辑漏洞:忽略了“1楼向下移动到-1楼”“-1楼向上移动到1楼”的特殊场景,初期直接用currentLayer++currentLayer--,导致楼层数值错误。后续添加了条件判断,处理1与-1的转换逻辑。
  3. 输入解析异常未捕获:初期未处理输入中“非数字字符”“逗号缺失”等无效格式,导致程序直接崩溃。后来添加NumberFormatException捕获,忽略无效请求,提升程序健壮性。
  4. 方向决策逻辑混乱:初期未考虑“无同方向请求时切换方向”的场景,导致电梯在某一方向空驶到底才切换,后来优化getDirection()方法,通过判断未处理请求的位置关系动态调整方向。

第二次作业

  1. 外部请求去重维度错误:初期仅按“楼层”去重,导致同一楼层的上行和下行请求被误判为重复,比如同时存在<5,UP><5,DOWN>时,后者被过滤。后来修正为按“楼层+方向”组合去重,解决该问题。
  2. 队列遍历并发问题:初期在遍历队列去重时直接修改队列元素(remove()),导致ConcurrentModificationException。后来改为先遍历队列记录重复元素,再统一删除,避免并发修改异常。
  3. 去重逻辑冗余:初期在内部请求和外部请求的去重方法中写了大量重复代码,后来提取通用的“队列元素判断”方法,提升代码复用性。
  4. 忽略队列空值判断:在遍历队列去重时,未判断队列是否为空,导致空指针异常。后来在所有遍历操作前添加isEmpty()校验,增强代码稳定性。

第三次作业

  1. 乘客方向推导错误:初期误将“源楼层>目的楼层”判定为UP,导致电梯方向与乘客需求相反,无法正常接客。后来修正Passenger.getDirection()方法,通过“目的楼层>源楼层”判断上行,解决方向匹配问题。
  2. 忘记添加目的楼层到内部队列:初期处理外部请求时,仅将Passenger对象出队,未将其目的楼层加入内部队列,导致乘客上车后电梯不前往目的地。后来在外部请求处理逻辑中新增innerRequests.add(passenger.getTargetFloor()),并确保加入前执行去重。
  3. 未过滤无效乘客请求:初期未校验“源楼层==目的楼层”的请求,导致这类无效请求被加入队列,电梯无意义停靠。后来在输入解析时添加条件判断,直接过滤该类请求。
  4. 方向决策适配失败:初期未修改getDirection()方法,仍试图获取原OuterRequest的方向属性,导致空指针异常。后来将方法中所有依赖外部请求方向的逻辑,改为调用Passenger.getDirection(),完成适配。

改进建议

  1. 优化请求优先级机制:当前程序采用“先进先出”策略,可新增优先级设计(如紧急请求标识),让特殊需求(如急救、消防)优先处理,更贴近实际电梯使用场景。
  2. 升级方向决策算法:当前“同方向优先”逻辑较为基础,可引入LOOK算法(电梯驶向最远请求楼层,途中处理同方向请求,减少空驶距离),提升运行效率。
  3. 增加电梯状态可视化:新增“当前载重”“乘客数量”“剩余请求数”等属性,在输出中显示,让程序运行状态更直观,便于调试与用户理解。
  4. 强化输入容错性:当前仅忽略无效请求,可新增用户提示(如“输入格式错误,请按<源楼层,目的楼层>格式输入”“楼层超出范围,有效范围为X-Y”),提升交互体验。
  5. 支持实时动态输入:当前程序一次性读取所有输入后再运行,可引入多线程,让电梯在运行过程中实时接收新请求,更符合实际使用场景(乘客随时呼叫电梯)。
  6. 增加日志记录功能:通过Logger或文件输出,记录请求发起时间、处理时间、电梯状态变化等信息,便于追溯问题与优化逻辑。
  7. 优化去重效率:当前通过遍历队列去重,时间复杂度为O(n),可引入HashSet存储已存在的请求特征(如内部请求存楼层,外部请求存“源楼层+方向”),将去重时间复杂度降至O(1)。

总结

三次电梯调度程序作业是“基础搭建-优化迭代-重构升级”的完整实践过程,让我对Java面向对象编程与业务逻辑实现有了更深刻的理解:

  • 从技术层面,逐步掌握了类的封装、集合框架的灵活应用、复杂流程的控制,以及输入输出的异常处理,提升了代码的健壮性与可维护性。
  • 从设计层面,体会到“先满足功能,再优化体验,最后重构模型”的迭代开发思路,尤其是第三次Passenger类的引入,让我理解了“用对象封装完整业务实体”的重要性,使代码更贴近现实场景、更具扩展性。
  • 从问题解决层面,每次作业遇到的“方向决策错误”“去重逻辑漏洞”“请求转换衔接”等问题,让我学会了通过“拆解需求-定位核心-逐步调试”的方式解决复杂问题,同时注重代码的兼容性与容错性。

此次实践也让我认识到,程序开发不是“一蹴而就”的,而是在不断迭代中完善的。每一次作业的改进,都是对前一次不足的弥补,最终实现从“能运行”到“运行好”再到“设计优”的提升。未来,可基于现有框架,进一步探索更复杂的电梯调度场景(如多部电梯协同、动态请求处理),持续提升技术应用与问题解决能力。

posted on 2025-11-21 14:40  天道555555  阅读(0)  评论(0)    收藏  举报