单部电梯调度程序三次迭代设计与实践总结 - 23207231

news/2025/11/22 15:37:35/文章来源:https://www.cnblogs.com/ZhangYuxuan123/p/19256920

一、前言

本次共完成三次题目集训练,核心围绕 “单部电梯调度程序” 的迭代开发展开,辅以基础语法与逻辑验证类题目,整体呈现递进式训练节奏。以下从知识点覆盖、题量分布与难度梯度三方面进行总结:

(一)知识点覆盖

三次题目集始终以 “面向对象编程(OOP)” 为核心,逐步扩展知识边界:

题目集 1:聚焦基础语法与单一类功能实现,涉及LinkedList队列操作、正则表达式(Pattern/Matcher)请求解析、分支与循环逻辑控制,核心目标是让开发者掌握 “需求转化为代码” 的基本能力,理解电梯调度的核心规则(同向优先、逐层移动、状态切换)。

题目集 2:引入 “单一职责原则(SRP)”,要求拆分类职责,新增enum枚举(Direction/State)管理电梯方向与状态、ExternalRequest类封装外部请求,同时涉及请求去重逻辑(连续重复请求过滤)与类间协作(电梯类 - 队列类 - 控制类的交互),重点训练类设计与模块化思维。

题目集 3:优化数据模型,取消独立请求类,新增Passenger类封装乘客属性(源楼层、目的楼层),外部请求格式从 “楼层 + 方向” 改为 “源楼层 + 目的楼层”,并新增 “外部请求处理后自动转为内部请求” 的业务逻辑,进一步贴近真实电梯场景,同时强化类间依赖管理与业务流程衔接。

(二)题量与难度分布

三次题目集均以 “单部电梯调度程序” 为核心,难度呈上升:

题目集 1:测试点只有一个占了题目集的70分,在判断电梯移动方向理解上有问题,核心挑战在于 “正确解析请求格式” 与 “实现同向优先调度逻辑”。

题目集 2:在上一个的基础上进行了 “类职责拆分” 与 “请求去重”。

题目集 3:在前两个的基础上修改,请求封装成了乘客请求,对外部请求的格式和处理进行了改进,应该是功能具体实现上漏写了什么情况,导致一个测试点没过。

二、设计与分析

(一)题目集 1:单一类架构与基础调度实现

  1. 架构设计

采用 “少类多职责” 的简化设计,核心类仅 3 个:RequestNode(请求数据封装)、RequestQueue(请求存储与管理)、Elevator(核心调度逻辑),Main类负责输入输出与初始化。整体架构无明确的模块划分,Elevator类承担了 “请求解析”“状态管理”“调度算法”“输出控制” 四大核心职责,类间依赖关系简单但耦合度极高(Elevator直接操作RequestQueue的内部队列)。

类图如下:

image

  1. 核心逻辑分析

请求解析与存储:通过两个正则表达式分别匹配内部请求(^<(\\d+)>$)与外部请求(^<(\\d+),\\s*(UP|DOWN)\\s*>$),解析后通过RequestQueue的addNode方法加入队列,仅在添加时判断楼层有效性与当前楼层重复性,未对非数字格式请求进行严格过滤,存在 “无效数据进入队列” 的潜在风险。

调度算法:采用 “同向优先 + 输入顺序” 的调度策略,通过findSameDirByInputOrder方法遍历队列,查找当前方向上首个符合条件的请求(UP 方向找大于当前楼层的请求,DOWN 方向找小于当前楼层的请求);无同向请求时立即切换方向,仍无则匹配任意状态符合的请求。该算法实现简单,但未考虑请求与当前楼层的距离,可能导致 “绕路” 问题(如当前楼层 5,存在请求 3(UP)与 7(UP),按输入顺序先处理 3 再处理 7,多移动 4 层)。

状态管理与停站处理:电梯状态通过 “是否有请求” 与 “当前楼层是否等于目标楼层” 间接判断,无明确的State枚举;到达目标楼层后,根据队列大小判断处理逻辑 —— 若仅剩最后一个请求,同时移除该楼层的所有类型请求(UP/DOWN/DES),否则按 “同向外部请求优先,内部请求次之” 的顺序处理

  1. 性能与架构评估:基于 SourceMonitor 的量化分析

image

通过 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(入口类):仅负责输入读取、组件初始化与调度启动,不参与业务逻辑,实现 “入口与核心逻辑分离”。

类图如下:

image

2.核心逻辑优化

请求去重逻辑:内部请求通过 “判断当前请求与队尾请求的楼层是否一致” 实现去重;外部请求通过重写ExternalRequest的equals方法,同时比较 “楼层 + 方向” 实现精准去重,解决了题目集 1 中 “连续相同请求重复处理” 的问题。例如输入<3,UP>三次,队列仅保留 1 个有效请求,提升了调度效率。

方向确定算法:Controller的determineDirection方法采用 “常规逻辑 + 兜底逻辑” 的分层策略:

常规逻辑 1:若当前方向有同向请求,保持方向不变;

常规逻辑 2:若当前方向无请求,切换至反向检查,有则切换方向;

初始逻辑:若电梯处于 IDLE 状态,优先尝试 UP 方向,再尝试 DOWN 方向;

兜底逻辑:若所有常规方向无目标但仍有请求,强制前往剩余请求楼层。该策略确保了方向判断的全面性,避免了 “请求遗漏” 或 “方向频繁切换” 的问题。

状态管理与移动控制:通过State枚举明确电梯状态,move方法触发时设置状态为MOVING,开门时切换为STOPPED,状态切换可追溯;移动逻辑采用 “一层一步” 模式,每次移动后检查是否需要停站,确保 “顺路请求不遗漏”。

3.性能与架构评估:量化指标的显著改善

image

通过 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 中 “仅处理队头请求,顺路请求遗漏” 的问题。

类图如下:

image

2.核心逻辑

乘客模型的统一封装:Passenger类通过两个构造方法分别适配内部请求(仅目的楼层)与外部请求(源楼层 + 目的楼层),统一了数据格式,避免了题目集 2 中 “内部请求为 Integer 类型,外部请求为对象类型” 的不一致问题;getDirection方法自动计算方向,减少了请求解析时的方向判断逻辑,让外部请求格式从 “楼层 + 方向” 改为更贴近真实场景的 “源楼层 + 目的楼层”(如<5,9>表示 5 楼乘客要去 9 楼)。

外部请求的处理:当电梯到达外部乘客的源楼层并开门时,Controller的openDoorAndProcess方法会移除外部队列的该乘客,并将其目的楼层作为内部请求加入内部队列,模拟了 “乘客进梯后按下目的楼层” 的真实操作。例如外部请求<5,9>处理后,内部队列自动新增目的楼层 9 的请求。

调度算法的优化:findTargetFloor方法采用 “双层筛选” 策略:

第一层(同向最近):查找当前方向上,距离当前楼层最近的内 / 外部请求(内部请求看目的楼层,外部请求看源楼层);

第二层(全局最近):若当前方向无目标,计算所有内 / 外部请求与当前楼层的距离,选择最近目标。该算法解决了题目集 2 中 “按输入顺序调度导致的绕路问题”,例如当前楼层 5,内部请求 8、外部请求 10(UP 方向),优先处理 8 而非 10,减少了 2 层的无效移动。

  1. 性能与架构评估:场景适配后的指标优化

image

通过 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. 现存问题

题目集 1 的parseAndAddRequest方法仅对 “楼层范围” 和 “当前楼层重复性” 进行校验,未处理非数字格式请求(如<abc>)和空请求(如<>),导致无效数据进入RequestQueue,进而引发getNextTarget方法计算目标楼层时出现逻辑错误(如无限循环、空指针异常)。例如输入<25>(最大楼层 20)时,程序会持续输出 “Current Floor:20 Direction:UP”,无法终止。

  1. 具体优化方案

在Elevator类的parseAndAddRequest方法中,新增 “格式合法性 + 数据类型” 的双重校验逻辑,步骤如下:

格式预校验:在正则匹配前,先判断请求字符串是否符合 “<开头、>结尾” 的基础格式,若不符合直接忽略(如输入 “3,UP”“<3,up>” 等格式错误请求);

数字类型校验:解析楼层字符串时,用try-catch捕获NumberFormatException,非数字格式(如<abc>)直接忽略;

(二)题目集 2:引入 “接口抽象” 降低类间耦合,解决 “扩展困难” 问题

  1. 现存问题

题目集 2 中Controller类直接依赖RequestQueue和Elevator的具体实现(如queue.getInternalRequests().peek()),而非接口。

      2. 具体优化方案

定义IRequestQueue和IElevator两个接口,封装核心操作方法,让RequestQueue和Elevator实现接口,Controller仅依赖接口而非具体类,实现 “依赖倒置”。

(三)题目集 3:

没改进建议,测试点有一个没过。

 

五、总结

(一)学习收获

熟练掌握了队列、正则表达式、枚举、类间协作等核心技术的应用,能够快速将业务需求转化为技术实现;

理解并实践了单一职责原则、依赖倒置原则、开闭原则等架构设计原则,能够设计 “高内聚、低耦合” 的模块化系统;

建立了 “需求拆解” 的工程化思维,能够将复杂业务规则(如电梯调度)拆解为可执行的模块与方法。

(二)需进一步学习的方向

当前仅初步应用了单一职责原则与观察者模式的思路,对工厂模式、策略模式、单例模式等的应用场景与实现方式理解不深,后续需系统学习设计模式,并在实际项目中实践,提升架构设计的灵活性。

(三)课程与教学改进建议

适当增加测试点;示范样例更体现题目核心逻辑。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/973169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

格路计数的一类(降维?)技巧

模拟赛考到了,记录一下。 题面: 给你二维平面上 \(n\) 个点,定义移动:$(x,y) \to (x+1,y) / (x-1,y) / (x,y+1) / (x,y-1) $(一个点可以移动到上下左右与这个点相邻的点)。移动每个点 \(m\) 次,使得最后这些点的…

百度PaddleOCR-VL:基于0.9B超紧凑视觉语言模型,支持109种语言,性能超越GPT-4o等大模型 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

hadoop处理mysql数据的性能瓶颈

Hadoop处理MySQL数据时可能会遇到多个性能瓶颈,主要包括以下几个方面:数据导入速度慢:将MySQL中的数据导入Hadoop需要经过抽取、转换和装载(ETL)的过程。如果数据量较大,ETL过程可能会耗费较长时间,导致性能瓶颈…

hadoop在linux的安装

在 Linux 系统上安装 Hadoop 需要以下几个步骤:一、系统环境准备确保你的 Linux 系统满足以下要求:Linux 发行版:如 Ubuntu 20.04 LTS、CentOS 7/8、Debian 11 等。Java:Hadoop 需要 Java 8 或更高版本。磁盘空间:…

hadoop与mysql的综合应用解决方案

Hadoop与MySQL的综合应用解决方案通常涉及大数据处理与关系型数据库的整合。以下是一个综合应用解决方案的概述: 1. 数据存储层Hadoop HDFS:用于存储海量非结构化数据,如日志文件、图像、视频等。HDFS具有高容错性和…

hadoop与mysql的数据同步方法

Hadoop与MySQL的数据同步可以通过多种方法实现,以下是其中两种常见的方法:使用Sqoop进行数据同步:Sqoop是一个开源的数据导入导出工具,它允许将数据从一个关系型数据库(如MySQL)导入到Hadoop的HDFS(Hadoop Dist…

详细介绍:2. 容器常用操作

详细介绍:2. 容器常用操作pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", …

2025年上海黑臭水体修复服务权威推荐榜单:黑臭水体治理方案/河道水净化公司/河道治理服务商精选

黑臭水体治理作为城市环境治理的重要环节,其技术先进性与工程实施能力直接关系到治理效果与长效保持。专业修复服务商正成为上海改善水环境质量的关键力量。 随着城市化进程加快与水环境治理要求提高,上海黑臭水体修…

2025年KBK刚性组合式起重机供应商权威推荐榜单:KBK起重机/KBK柔性组合式起重机/KBK刚性吊源头厂家精选

KBK刚性组合式起重机作为现代工业物料搬运的关键设备,其结构稳定性、模块化程度与负载能力直接关系到生产效率和作业安全。选择专业供应商成为企业优化生产流程的重要环节。 KBK刚性组合式起重机系统由标准化的刚性轨…

珠海爱尔眼科医院联系方式:常见眼病防治建议

一、官方联系方式 珠海爱尔眼科医院电话:0756-3331677 微信号:18998173482 官网:http://www.aier0756.com 二、使用建议与提醒 在就诊前建议通过电话或官网了解科室设置与专家排班信息,合理安排时间。医院提供全生…

一条SQL的完整执行过程:小明查询员工信息的完整冒险故事

MySQL执行SQL的全流程,从"接待"到"找数据"再到"返回结果",让你彻底理解数据库背后的秘密第一章:敲门入室——连接层的"前台接待" 故事开场:小明(应用程序)想要查询公司…

LangGraph 官方教程:聊天机器人之三 - 实践

LangGraph 官方教程:聊天机器人之三 - 实践2025-11-22 15:20 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: bl…

2025年不锈钢管锯片供货厂家权威推荐榜单:切H型钢/角钢切割/切碳素钢锯片源头厂家精选

在制造业转型升级的推动下,不锈钢管锯片以其高切割精度和卓越的耐用性,正成为金属加工、管道安装和建筑行业不可或缺的工具。 随着制造业的发展,市场对不锈钢管锯片的需求持续增长。据行业报告显示,2025年全球工业…

2025年一体式泵站生产厂家权威推荐榜单:污水一体化泵站/预制泵站/雨水泵站源头厂家精选

在城市化进程和环保要求不断提高的背景下,一体式泵站以其安装便捷、智能高效的特点,正成为市政排水、污水处理领域的优选方案。 根据行业报告,全球一体式泵站市场在2025-2031年间预计将保持稳定增长,其中智能化、模…

gzip linux

gzip 是一个用于压缩和解压缩文件的命令,它属于 GNU 压缩工具集的一部分。gzip 通常用于压缩文件(如 .txt、.log、.dat 等)并将其转换为 .gz 格式。? 常用 gzip 命令1. 压缩文件gzip filename作用:将指定文件压缩…

gz文件 linux

当然可以!关于 gz 文件(即 gzip 压缩文件),以下是一些常见的 Linux 命令和脚本,用于解压、压缩、查看 gz 文件内容等操作。一、压缩文件(.gz)1. 使用 gzip 命令压缩文件gzip filename.txtfilename.txt 是要压缩…

hadoop for linux 安装

安装 Hadoop 在 Linux 系统上是一个常见的分布式计算任务。Hadoop 是一个基于 Java 的开源框架,用于分布式存储和计算。以下是安装 Hadoop 的常见步骤,适用于大多数 Linux 发行版(如 Ubuntu、CentOS、Debian 等)。…

WPF 数据绑定通过 ElementName 失效后改为 Reference 正常

WPF 数据绑定通过 ElementName 失效后改为 Reference 正常原代码如下,运行正常:<Grid><Grid x:Name="gridMenus" Visibility="Collapsed"><Grid.ContextMenu><ContextMenu&…

2025年塑胶跑道面层环境测试舱直销厂家权威推荐榜单:塑胶跑道环境舱/2舱塑胶跑道环境舱/4舱塑胶跑道环境舱源头厂家精选

在校园体育设施与绿色建筑标准不断提升的今天,塑胶跑道面层环境测试舱作为材料环保性能验证的关键设备,其检测精度与数据可靠性直接关系到跑道产品的环境安全性与合规性。 塑胶跑道面层环境测试舱是模拟特定温度、湿…

Doubao-Seed-Code VS Kimi K2 VS DeepSeek评测体验:国内首个支持视觉理解能力的编程模型

Doubao-Seed-Code VS Kimi K2 VS DeepSeek评测:国内首个支持视觉理解能力的编程模型,专为 Agentic Coding 任务深度优化的全新代码模型 摘要 本文基于火山引擎体验中心,同步评测对比 Doubao-Seed-Code preview-2510…