第一次blog作业

一、前言

在这三次题目集中,主要围绕电梯调度程序展开,涵盖了丰富的知识点。从基础的Java语法应用,到面向对象设计原则如单一职责原则(SRP)的实践,逐步深入。题量上,每次都需要完成一个相对完整的电梯调度程序设计,且随着迭代要求不断细化和扩展。难度方面,呈现出循序渐进的特点,从最初简单实现电梯运行逻辑,到后续不断拆分职责、优化结构,对代码的可读性、可维护性以及逻辑的严谨性要求越来越高。

二、设计与分析

第一次设计:
设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层。
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:

运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例:
在这里给出一组输入。例如:

1
20
< 3,UP >
<5>
<6,DOWN>
<7>
<3>
end
输出样例:
在这里给出相应的输出。例如:

Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
代码分析结果:

代码行数(Lines):139行
语句数(Statements):80 条
分支语句占比(% Branches):20.0%
方法调用语句数(Calls):48
注释行占比(% Comments):15.1%
类和接口数(Classes):2
平均每类方法数(Methods/Class):4.08
平均每方法语句数(Avg Stmts/Method):8.38
最大复杂度(Max Complexity):2
最大嵌套深度(Max Depth):4
平均嵌套深度(Avg Depth):1.64
最复杂方法行号(Line Number of Most Complex Method ):113

第二次设计:
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类,具体设计可参考如下类图。

电梯运行规则与前阶段单类设计相同,但要处理如下情况:

乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>
注意:本次作业类设计必须符合如上要求(包含但不限于乘客请求类、电梯类、请求队列类及控制类,其中控制类专门负责电梯调度过程),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次电梯程序提交到本次题目中测试)。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:

运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例1:
在这里给出一组输入。例如:

1
20
< 3,UP>
<5>
< 6,DOWN>
<7>
<3>
end
输出样例1:
在这里给出相应的输出。例如:

Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
输入样例2:
在这里给出一组输入。例如:

1
20
< 3,UP>
< 3,UP>
<5>
<5>
<5>
<6,DOWN>
<7>
<7>
<3>
<22,DOWN>
<5,DOWN>
<30>
END
输出样例2:
在这里给出相应的输出。例如:

Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Open Door # Floor 5
Close Door
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
代码分析为:

代码规模相关
Lines(行数):306 行
Statements(语句数):176 条
结构复杂度相关
% Branches(分支语句占比):15.9%
Max Complexity(最大复杂度):17
Max Depth(最大深度):6
Avg Depth(平均深度):2.17
方法相关
Methods/Class(平均每类方法数):4.86
Avg Stmts/Method(平均每方法语句数):3.56
Calls(方法调用语句数):99
注释情况
% Comments(注释行占比):0.0%
其他
Classes(类和接口数):7
Line Number of Most Complex Method(最复杂方法行号):203

第三次设计:
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计可参考如下类图。

电梯运行规则与前阶段相同,但有如下变动情况:

乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)
注意:本次作业类设计必须符合如上要求(包含但不限于设计电梯类、乘客类、队列类以及控制类),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次及第二次电梯程序提交到本次题目中测试)。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<请求源楼层,请求目的楼层>,其中,请求源楼层表示乘客发起请求所在的楼层,请求目的楼层表示乘客想要到达的楼层。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:

运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例1:
在这里给出一组输入。例如:

1
20
<5,4>
<5>
<7>
end
输出样例1:
在这里给出相应的输出。例如:

Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Open Door # Floor 5
Close Door
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
输入样例2:
在这里给出一组输入。例如:

1
20
<5,9>
<8>
<9,3>
<4>
<2>
end
输出样例2:
在这里给出相应的输出。例如:

Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Open Door # Floor 8
Close Door
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
Current Floor: 3 Direction: DOWN
Current Floor: 2 Direction: DOWN
Open Door # Floor 2
Close Door
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door

测试结果:

代码规模
Lines(行数):327 行
Statements(语句数):183 条
结构复杂度
% Branches(分支语句占比):16.4%
Max Complexity(最大复杂度):13
Max Depth(最大深度):6
Avg Depth(平均深度):2.20
方法相关
Methods/Class(平均每类方法数):5.14
Avg Stmts/Method(平均每方法语句数):3.53
Calls(方法调用语句数):97
注释情况
% Comments(注释行占比):0.6%
其他
Classes(类和接口数):7
Line Number of Most Complex Method(最复杂方法行号):213

三、踩坑心得

第一次设计

  • 问题:最初版本代码将众多功能集中在一个类中,导致电梯类职责过多。例如,既负责处理请求,又要控制运行逻辑和输出。在测试时,对于复杂请求序列,如连续的相同请求和不合理楼层请求,处理逻辑混乱,经常出现错误的运行路径和输出结果。
  • 原因分析:从类设计结构看,缺乏职责分离意识,没有将请求处理、运行控制等功能拆分。流程图上表现为各功能模块交织在一起,没有清晰的边界。例如,在添加请求时,既要判断请求类型又要处理运行逻辑,导致代码耦合度高。
  • 解决方式:增加了请求队列类来专门管理请求,将请求的添加、过滤等操作从电梯类中分离出来。通过引入方向和状态枚举,清晰界定电梯的运行状态,使电梯类专注于自身状态管理和运行控制。

第二次设计

  • 问题:在第二次迭代引入乘客类并修改请求格式后,出现了外部请求处理后,目的楼层未正确加入内部队列的情况。同时,在处理不同方向请求切换时,逻辑出现混乱,导致电梯运行不符合预期。
  • 原因分析:从类设计结构角度,乘客类、请求队列类和控制类之间的交互出现问题。在控制类处理请求时,对外部请求处理后的逻辑转换不够清晰。流程图中可以看到,外部请求处理流程与内部请求添加流程之间缺乏有效衔接。在测试中,通过不同请求序列的输入,发现问题集中在外部请求处理后的逻辑分支上。
  • 解决方式:在控制类的openDoors方法中,明确外部请求出队后将目的楼层加入内部队列的逻辑。同时,优化方向切换时的判断逻辑,在determineDirection和getNextFloor方法中,增加对请求队列状态的全面判断,确保电梯在不同方向请求间能够正确切换运行路径。

第三次设计

  • 问题:在进一步优化代码时,发现代码在处理大量请求时效率较低,尤其是在查找最近请求楼层的算法上,时间复杂度较高。此外,在处理重复请求过滤时,虽然功能实现,但代码不够简洁高效。
  • 原因分析:从类设计结构看,部分方法在不同类中存在重复逻辑,如在判断请求是否存在时,内部请求队列和外部请求队列的处理逻辑相似但未抽象。在算法层面,查找最近楼层采用的遍历方式在数据量增大时效率明显降低。通过性能测试工具分析,发现查找楼层操作占用大量时间。
  • 解决方式:对重复逻辑进行抽象,提取出通用方法。在查找最近楼层算法上,采用更高效的数据结构和算法,如使用优先级队列来维护请求楼层,降低查找的时间复杂度。同时,优化重复请求过滤逻辑,使用更简洁的集合操作来实现。

四、改进建议

代码结构方面
进一步强化模块化设计,将电梯运行的不同功能,如请求处理、路径规划、状态控制等,拆分成更小的类或接口,降低类之间的耦合度。例如,可以单独设计一个路径规划类,专门负责根据请求队列计算电梯的最优运行路径,使各模块职责更加清晰。
性能优化方面
对于大规模请求场景,考虑使用更高级的数据结构和算法。例如,使用哈希表来存储请求队列,提高请求的查找和添加效率。同时,引入多线程技术,在不影响电梯运行逻辑正确性的前提下,提高程序的并发处理能力,减少响应时间。
代码测试方面
增加单元测试和集成测试用例,覆盖各种边界情况和复杂请求序列。使用测试框架如JUnit,自动化测试过程,确保每次代码修改后功能的正确性和稳定性。同时,定期进行性能测试,监控程序在不同负载下的运行情况,及时发现性能瓶颈并进行优化。

五、总结

学习收获
通过这三次题目集的练习,深入掌握了Java面向对象编程的核心概念和设计原则。从最初对单一职责原则的模糊理解,到能够熟练应用该原则对代码进行重构和优化,实现了质的飞跃。同时,在算法设计和数据结构应用方面也得到了锻炼,学会根据不同场景选择合适的数据结构来提高程序性能。此外,对程序调试和问题排查能力有了很大提升,通过分析错误日志、使用调试工具等方式,能够快速定位和解决代码中的问题。
需进一步学习研究的方向
多线程编程在实际项目中的应用还不够熟练,尤其是在处理线程安全和同步问题上,需要进一步深入学习。对于复杂系统的架构设计,如何在满足功能需求的同时,兼顾可扩展性、可维护性和性能优化,还需要更多的实践和理论学习。此外,在代码的自动化测试方面,虽然引入了JUnit,但对于测试覆盖率的提升和测试用例的优化,还有很大的提升空间。
对课程及作业的建议
希望在课程讲解中,增加更多实际项目案例的分析,特别是与课程知识点紧密结合的企业级项目案例,帮助我们更好地理解知识点在实际场景中的应用。对于作业,可以在每次迭代题目中,提前给出一些可能的优化方向和提示,引导我们在完成基本功能的基础上,进一步思考代码的优化和拓展。同时,增加一些小组讨论或代码评审环节,促进同学之间的交流和学习,从不同角度发现代码中的问题和改进思路。

posted @ 2025-04-20 21:06  刘昊宇  阅读(23)  评论(0)    收藏  举报