1.前言:在学习 Java 面向对象编程的过程中,电梯调度程序系列题目无疑是一次极具挑战性且收获颇丰的实践之旅。这一系列题目共包含三道,从基础的单类设计逐步迭代为复杂的多类设计,层层递进,全方位考察了我们对类的设计、数据结构、算法逻辑以及代码优化的掌握程度。
从知识点层面来看,这些题目深度融合了众多核心内容。首先,面向对象编程思想贯穿始终,从最初简单的电梯类设计,到后续遵循单一职责原则(SRP)进行多类拆分,要求我们合理划分类的职责,实现高内聚低耦合。在类的设计过程中,涉及到类的属性封装、方法定义,以及类与类之间的交互协作,比如电梯类、乘客类、队列类和控制类之间的关系构建。其次,数据结构的运用不可或缺,请求队列的管理是关键,通过队列来存储乘客的请求,实现先进先出的处理逻辑,同时还需要处理请求队列中的重复请求、无效请求等特殊情况。再者,算法逻辑的设计直接影响电梯调度的合理性,如电梯运行规则的实现 —— 优先处理同方向请求,在移动过程中处理顺路请求等,这要求我们对条件判断、流程控制有清晰的思路。
题量方面,虽然仅有三道题目,但每一道题都需要投入大量的时间和精力去思考、设计与实现。每道题的需求描述详尽,包含了多种输入输出样例,以确保我们能够全面理解题目要求,并且通过这些样例来验证代码的正确性。
难度上,三道题目呈现出阶梯式上升的特点。第一道题要求设计一个包含多种属性和方法的电梯类,实现基本的电梯调度功能,属于中等难度,重点在于对电梯运行逻辑的梳理和代码实现。第二道题在第一道题的基础上进行迭代,引入多类设计,遵循单一职责原则,不仅要考虑电梯调度逻辑,还要合理划分各个类的职责,处理无效请求和重复请求,难度有所提升。第三道题再次迭代,加入乘客类,改变乘客请求输入方式,进一步复杂了请求处理逻辑,同时要保证电梯运行规则的正确实现,属于较难级别,对综合编程能力提出了更高的要求。
2.设计与分析
一.


在第一次作业中,我的程序因为运行超时问题未能得分,以下是我的代码的具体分析
行数(Lines):该文件有 220 行代码,属于中等规模的文件。行数较多可能意味着代码实现的功能相对复杂,维护时可能需要花费更多时间来理解代码逻辑。
语句(Statements):共有 121 条语句,平均每行代码包含的语句数量相对合理,不过这也会受到代码风格和格式的影响。
代码结构相关
类和接口(Classes and Interfaces):仅有 2 个类,说明代码的结构相对简单,没有过多的类之间的层次和交互。
每个类的方法数(Methods per Class):平均每个类有 5.5 个方法,方法数量不算多,可能表示每个类的职责相对单一,但也存在一个类承担了过多功能的情况。
每个方法的平均语句数(Average Statements per Method):为 10.09 条语句,这表明方法的长度适中,不过方法的功能和逻辑复杂度一般
代码复杂度相关
分支语句百分比(Percent Branch Statements):占 26.4%,说明代码中有一定比例的条件判断语句(如 if、switch 等),这会增加代码的逻辑复杂度,在测试和维护时需要考虑不同分支的情况。
最大复杂度(Maximum Complexity):为 6,出现在 Main.main() 方法中。复杂度相对不算太高,但如果后续代码不断扩展,可能需要关注方法的复杂度是否会持续上升,导致代码难以理解和维护。
最深块深度(Maximum Block Depth):达到 5,同样出现在 Main.main() 方法中,说明 main 方法中存在多层嵌套的代码块(如循环、条件语句的嵌套),这会使代码的逻辑变得复杂,可读性和可维护性降低。
注释相关
带注释的行百分比(Percent Lines with Comments):仅为 8.6%,注释比例较低,这对于代码的可读性和可维护性是不利的。在后续开发或维护过程中,需要添加更多注释来帮助理解代码的功能和逻辑。
方法调用相关
方法调用语句(Method Call Statements):有 46 条,说明代码中存在较多的方法调用,这是正常的代码结构表现,但需要关注方法调用的合理性和方法之间的依赖关系,避免出现过度耦合的情况。


第一次题目我的问题比较大,在面对复杂的程序问题时慌了手脚,同时在面对类中的方法较多的情况下未能熟练的把握对各方法的调用。在心态上也较为慌张,导致了不少问题。同时,我的很多代码都是重复性的,导致多段代码实现的功能其实是一致的,所以会冗长繁复,导致运行超时。
二.

这一次的题目是对上一次题目的迭代优化,目的是满足类的单一变量原则,解决电梯类职责过多的问题。
以下是对代码的分析
行数(Lines):该文件有 279 行代码,属于规模相对较大的文件。较多的行数可能意味着代码实现的功能较为复杂,后续在理解和维护代码时,可能需要花费更多的时间和精力来梳理代码结构和逻辑。
语句(Statements):共有 149 条语句,平均每行代码包含的语句数量不算密集,但由于行数较多,整体的语句量也相对可观。这也反映出代码在功能实现上有一定的复杂性。
代码复杂度相关
分支语句百分比(Percent Branch Statements):占 22.1%,说明代码中有一定比例的条件判断语句(如 if、switch 等)。这些分支语句会使代码的执行路径变得复杂,增加了代码的逻辑复杂度。在测试和维护时,需要考虑不同分支的情况,以确保代码在各种输入条件下都能正确运行。
最大复杂度(Maximum Complexity):为 8,出现在 Main.main() 方法中。复杂度达到 8 表明该方法的逻辑相对复杂,可能存在较多的条件判断、循环或嵌套结构。较高的复杂度会使方法难以理解和调试,后续在对该方法进行修改或扩展时,需要特别小心,以避免引入新的错误。
最深块深度(Maximum Block Depth):达到 5,同样出现在 Main.main() 方法中。这意味着 main 方法中存在多层嵌套的代码块(如循环、条件语句的嵌套)。深度较大的嵌套结构会使代码的逻辑变得更加晦涩,可读性降低,同时也增加了代码出错的可能性,在维护时需要花费更多时间来理清嵌套层次之间的关系。
平均块深度(Average Block Depth):为 1.49,整体平均块深度不算高,但由于存在最大块深度为 5 的情况,说明代码中部分区域的嵌套结构较为复杂。平均块深度可以反映代码整体的结构复杂度,较小的平均块深度通常意味着代码结构相对较为扁平,易于理解和维护。
注释相关
带注释的行百分比(Percent Lines with Comments):仅为 4.3%,注释比例极低。注释是代码可读性和可维护性的重要组成部分,过少的注释会使其他开发者(甚至是代码的原作者在一段时间后)难以快速理解代码的功能和逻辑。在后续的开发中,应该增加必要的注释,对关键代码段、算法逻辑、变量含义等进行说明,以提高代码的可理解性。
方法调用相关
方法调用语句(Method Call Statements):有 103 条,说明代码中存在大量的方法调用。这表明代码在功能实现上通过多个方法之间的协作来完成,虽然方法调用是面向对象编程中常见的方式,但过多的方法调用可能导致代码的调用关系复杂,增加调试和维护的难度。需要关注方法之间的依赖关系,确保方法调用的合理性,避免出现过度耦合的情况。

此次题目让我对类与类之间的关系更为了解,也意识到了遵循单一职责原则的重要性,其在提高可维护性.增强可读性和可理解性.降低耦合度等方面有着重要作用。同时,这次作业我也存在不少问题,例如类的组织不够清晰、方法数量过多、复杂度较高以及注释不足等,均需在之后的学习中慢慢改进。
三.

第三次题目是对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类。
以下是具体分析
行数(Lines):该文件有 253 行代码,属于中等规模。行数较多意味着代码实现的功能相对复杂,在阅读和维护时需要花费较多精力来梳理逻辑和结构。
语句(Statements):共有 128 条语句,平均每行代码包含的语句数量不算多。不过,结合行数来看,整体语句量也需要一定的时间和精力去理解和管理。
代码复杂度相关
分支语句百分比(Percent Branch Statements):占 22.7%,说明代码中有一定比例的条件判断语句(如 if、switch 等)。这些分支语句会增加代码的逻辑复杂度,使得代码的执行路径变得多样化。在测试和维护时,需要考虑不同分支的情况,以确保代码在各种输入条件下都能正确运行。
最大复杂度(Maximum Complexity):为 10,出现在 Main.main() 方法中。复杂度达到 10 表明该方法的逻辑比较复杂,可能包含较多的条件判断、循环或嵌套结构。较高的复杂度会使方法难以理解和调试,在对该方法进行修改或扩展时,需要特别小心,以避免引入新的错误。
最深块深度(Maximum Block Depth):达到 5,同样出现在 Main.main() 方法中。这意味着 main 方法中存在多层嵌套的代码块(如循环、条件语句的嵌套)。深度较大的嵌套结构会使代码的逻辑变得更加晦涩,可读性降低,增加了代码出错的可能性。在维护时,需要花费更多时间来理清嵌套层次之间的关系。
平均块深度(Average Block Depth):为 1.54,整体平均块深度不算高,但由于存在最大块深度为 5 的情况,说明代码中部分区域的嵌套结构较为复杂。平均块深度可以反映代码整体的结构复杂度,较小的平均块深度通常意味着代码结构相对较为扁平,易于理解和维护。
注释相关
带注释的行百分比(Percent Lines with Comments):仅为 5.5%,注释比例较低。注释是提高代码可读性和可维护性的重要手段,过少的注释会使其他开发者(甚至原作者在一段时间后)难以快速理解代码的功能和逻辑。在后续开发中,应该增加必要的注释,对关键代码段、算法逻辑、变量含义等进行说明。
方法调用相关
方法调用语句(Method Call Statements):有 83 条,说明代码中存在大量的方法调用。方法调用是面向对象编程中实现功能协作的常见方式,但过多的方法调用可能导致代码的调用关系复杂,增加调试和维护的难度。需要关注方法之间的依赖关系,确保方法调用的合理性,避免出现过度耦合的情况。

第三次题目与第二次题目在算法上没有较大的差剧,只是优化了对数据处理的方法。但未能从根本上解决代码逻辑复杂度高的问题,依然存在优化的空间。
3.采坑心得:电梯调度规则中的 “优先处理同方向请求” 看似简单,实际实现时却暗藏玄机。在处理多个不同方向请求交替出现的复杂场景时,程序经常出现方向判断错误,导致电梯运行混乱。例如,当电梯上行过程中,同时出现多个下行请求,原本计划在当前方向请求处理完后切换方向,但由于没有合理记录和更新电梯状态,导致电梯错误地继续上行。经过多次调试,通过引入状态变量记录电梯当前运行方向和状态,在每次处理请求前后动态更新这些变量,才使电梯调度逻辑符合预期。
4.改进建议
对于电梯调度程序代码的改进建议,主要可以从遵循单一职责原则、提高代码可读性、优化算法逻辑和增强代码健壮性等方面进行:
类结构与职责分离
进一步明确类职责:目前虽然有不同功能的类,但类之间的职责边界可以更加清晰。例如,RequestQueue 类目前同时管理外部请求队列和内部请求队列,可以考虑拆分成 ExternalRequestQueue 和 InternalRequestQueue 两个类,分别负责外部乘客请求和内部乘客请求的管理,这样职责更加单一,代码也更易于理解和维护。
提取公共逻辑:在 Elevator 类和 Controller 类中,有一些逻辑可以提取成更细粒度的方法。比如在 Elevator 类的 moveToFloor 方法中处理外部请求和内部请求的逻辑,可以分别提取成 processExternalRequest 和 processInternalRequest 方法,使 moveToFloor 方法更加简洁明了。
提高代码可读性
增加注释:目前代码的注释比例较低,应在关键方法、变量和复杂逻辑处添加注释。例如,在 Controller 类的 findNextFloor 方法中,对于复杂的查找逻辑添加注释,解释每一步的目的和作用,方便其他开发者理解代码意图。
优化算法逻辑
减少循环嵌套和复杂度:Controller 类的 findNextFloor 方法中存在较多的循环嵌套,导致方法复杂度较高(Main.main() 方法复杂度也较高)。可以尝试使用更高效的数据结构或算法来简化查找逻辑,降低时间复杂度。例如,可以使用 TreeSet 等有序数据结构来存储请求,以便更快速地查找符合条件的请求楼层。
提前处理无效请求:在读取用户输入时,可以在 Main 类中提前处理无效请求(如楼层超出范围等),避免无效请求进入请求队列,减少后续处理的复杂性。
提取通用方法:将一些通用的功能方法提取出来,以便在不同的类中复用。例如,判断楼层是否有效的方法可以提取到一个工具类中,供 Elevator 类和 Main 类等使用。
5.总结
在这完成这三次题目后,我再次认识到遵循单一职责原则的重要性,对于类之间的各种调用关系的了解与应用更加深刻与熟练。
但我同时也需要更多的去练习类的设计与类之间的调用,在各次作业中,我都是跟据题目给出的类图来进行编程,难以通过自身的能力去设计类与类之间的关系。

posted on 2025-04-20 21:17  阿尔威克  阅读(34)  评论(0)    收藏  举报