第一次Blog作业

一、前言

题目集5-7总结

  在过去的一个月的时间里,我们经历了题目集5-7的测试。

  题目集5,包含5个题目,前四个题目(求身份证号校验位,求解一元二次方程等)难度较小,主要考察Java基础语法(输入输出处理,字符串处理,数组的使用等),值得注意的是在求身份证号校验位题目中,检验输入的身份证号码是否为17位数字时有些困难,与C语言有所不同,需要借助使用正则表达式\d{17}来验证输入是否为 17 位数字。如果不是,输出Wrong Format并终止程序。第五个题目(单部电梯调度程序)则难度较大,主要涉及到的知识点是条件判断与逻辑控制算法,主要的困难是算法的设计。

  题目集6,包含3个题目,1、点与线,2、汽车风挡玻璃雨刷问题,3、单部电梯调度程。这个题目集考察的知识点主要是类的设计,想借助题目使学生更好的理解类设计的单一职责原则,提高代码的复用性。需要注意的是第二题汽车风挡玻璃雨刷问题主要由几个实体类和一个控制类组成,实体类负责描述汽车相关部件的特定属性,而控制类则起到协调和控制这些实体类的作用,通过控制类来调用实体类中的数据实现功能,实体类中的属性加上了private修饰,体现了Java语言中封装性的特点,这是在C语言中没有学习到的。前两个题目难度较小,根据老师上课所讲的内容即可完成,第三题依旧是电梯问题,主要问题是算法以及如何合理设计类。

  题目集7,包含3个题目,1、销售步枪问题,2、蒙特卡罗方法求圆周率,3、单部电梯调度程。第二个题目中我学习到了Java语言中随机数生成的方法。这个题目集依旧练习类的设计,认识面向对象编程,保证类设计的单一职责模式。前两个题目难度较小,第三题依旧是电梯问题,但需要改进算法。

二、设计与分析

1、第一次电梯题目的设计与分析

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

类图如下

Source Monitor分析结果:

分析如下:

  • Main类:初步对输入的信息进行处理,通过格式识别是内部请求还是外部请求,将<楼层数>处理为内部请求楼层数并传入Elevator类,,将<乘客所在楼层数,乘梯方向>处理为外部请求楼层数并传入Elevator类,循环读取用户输入的请求信息,直到输入 "end" 为止。

  • Elevator类:使用了两个整形数组inquest和outquest存储用户的内部请求和外部请求,整形变量inquestc和outquestc记录内部请求和外部请求的数量,整形outquestflag记录外部请求的运行方向,direction表示电梯的运行方向,curr表示电梯所处楼层。addinquest方法添加内部请求,addoutquest方法添加外部请求,Print方法通过传入的的电梯所在楼层和目标楼层进行输出,elevatorrun方法模拟电梯运行。

通过Source Monitor分析结果可以看出我的代码存在许多问题:

  • % Branches(分支语句占比):占 29.6% 。在我的代码中,为了解决电梯运行问题,我使用了大量if-else结构。大量的分支带来了许多问题,逻辑结构太过于复杂,代码的可读性和可维护性太低,修改起来非常困难。

  • % Comments(注释行占比):仅 2.6% 。注释是代码的重要组成部分,用来帮助理解和修改代码,而我的注释行占比仅为 2.6%,这大大增加了代码维护的成本和出错的风险,给修改带来了许多困难。

  • Avg Complexity(平均复杂度):为 14.40 。Max Complexity(最大复杂度):高达 57 。这意味着 Elevator 类中方法的复杂程度较高。这也是分支语句占比带来的问题。

心得
刚接触面向对象的Java语言,我对它的特点还不是特别了解,引入怀着学习C语言的心态学习Java,没有遵循Java语言的特点,如封装性,将状态变量和相应操作封装在一起,实现模块化与信息隐藏,我没有将Elevator类分成几个类分工实现功能,没有实现单一职责原则,代码复用性极差,牵一发而动全身,极难修改,在后续过程中应该改进。

2、第二次电梯题目的设计与分析

题目简介:对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类,电梯运行规则与前阶段单类设计相同,但要处理如下情况:。乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行。乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>

类图如下

Source Monitor分析结果:

分析如下:

  • Main类:初步对输入的信息进行处理,通过格式识别是内部请求还是外部请求,将<楼层数>处理为内部请求楼层数并传入Elevator类,,将<乘客所在楼层数,乘梯方向>处理为外部请求楼层数并传入Elevator类,循环读取用户输入的请求信息,直到输入 "end" 为止。

  • Controller类:实现操作,Print方法通过传入的的电梯所在楼层和目标楼层进行输出,elevatorrun方法模拟电梯运行。

  • Elevator类:min表示最小楼层,max表示最大楼层direction表示电梯的运行方向,curr表示电梯所处楼层。addinquest方法添加内部请求,addoutquest方法添加外部请求。

  • Inquest类:使用了数组inquest存储用户的内部请求,整形变量inquestc记录内部请求的数量。

  • Outquest类:使用了数组outquest存储用户的内部请求,整形变量outquestc记录内部请求的数量,整形数组outquestflag记录外部请求的运行方向。

通过Source Monitor分析结果可以看出我的代码存在问题:

  • Avg Complexity(平均复杂度):为 3.36 。Max Complexity(最大复杂度):高达 57 。迭代后平均复杂度有所降低,但最大复杂度依然很高,这是因为在elevatorrun方法中存在大量if-else的嵌套。

  • Avg Depth(平均深度):3.63 ,平均嵌套深度尚可,但仍说明代码存在一定嵌套结构,需进一步优化以提升可读性和维护性。

心得
在第二次电梯作业中,我遵循要求将电梯类分为了电梯类、乘客请求类、队列类以及控制类,但队列类设计出错,没有做好。同时,加入了对输入数据错误的处理,程序自动忽略此类输入,继续执行。对重复输入相同数据,自动过滤,仅保留一个运行。

3、第三次电梯题目的设计与分析

题目简介:对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类,电梯运行规则与前阶段单类设计相同,但要处理如下情况:。乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行。乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>

类图如下

Source Monitor分析结果:

分析如下:

  • Main类:初步对输入的信息进行处理,通过格式识别是内部请求还是外部请求,将<楼层数>处理为内部请求楼层数并传入Elevator类,,将<乘客所在楼层数,乘梯方向>处理为外部请求楼层数并传入Elevator类,循环读取用户输入的请求信息,直到输入 "end" 为止。

  • Controller类:实现操作,Print方法通过传入的的电梯所在楼层和目标楼层进行输出,elevatorrun方法模拟电梯运行。

  • Elevator类:min表示最小楼层,max表示最大楼层direction表示电梯的运行方向,curr表示电梯所处楼层。addinquest方法添加内部请求,addoutquest方法添加外部请求。

  • RequestQueue类:使用了数组inquest存储用户的内部请求,整形变量inquestc记录内部请求的数量。同时调用Passenger存储外部请求

  • Passenger类:使用了数组outquest存储用户的内部请求,整形变量inquestc记录内部请求的数量,整形数组outquestflag记录外部请求的运行方向。

通过Source Monitor分析结果可以看出我的代码存在问题:

% Branches(分支语句占比):18.5% ,在改进后,分支语句占比相对适中,表明代码有一定条件判断逻辑,但不算特别复杂,但还是偏多,可以再做优化。

  • Avg Complexity(平均复杂度):为 3.47 。Max Complexity(最大复杂度):高达 47 。迭代后平均复杂度有所降低,但最大复杂度依然很高。

  • % Comments(注释行占比):1.1% ,注释极少,不利于代码理解和维护,后期查看代码时难快速把握意图。

心得
在这一次迭代作业中,我进一步优化了我的代码,尽量减少了分支语句,将一些相同的内容合并,删除了部分if-else结构,一定程度上减小了复杂的,但复杂的还是太高了,应该再优化算法。

三、采坑心得

1、在第一次写单部电梯调度程序是,我没有认真审题,对于提高只是粗略的看了一眼,反而去研究了测试用例,就着测试用例照葫芦画瓢,代码写出来了,但与题意千差万别,可以通过样例,但其实一团糟。最后没有在规定的时间内修改完成,测试点也没有通过,这道题0分。

2、输出问题,在第一次电梯问题中输出“System.out.printf("Current Floor: %d Direction: UP\n",i);”,这里的电梯方向未使用Direction调取变量,这样不利于修改代码,应该改为“System.out.printf("Current Floor: %d Direction: %s\n",i,direction);”。

3、使用if-else多层嵌套,会使代码复杂度变得非常高。

4、不写注释会使修改代码变得非常困难,甚至过几天自己写的代码自己都需要花很多时间去理解。

四、改进建议

  1. 我应该改变在学习C语言形成的习惯,因为在学习C语言练习的题目偏简单,使用一个函数均可完成大部分功能不需要考虑类间关系,但Java不同,它是是纯粹的面向对象语言,需要考虑封装性,需要通过类的相互合作完成功能,同时,需要保证单一职责,一个类应该只负责一项明确的职责,每个类专注于自己的职责,那么在修改或扩展某一功能时,就不会对其他功能造成不必要的干扰,不会牵一发而动全身,提高可读性,增强可维护性和可复用性。

  2. 学习在写代码的过程中添加注释。在以后的学习与工作中,我们不仅要自己写代码,还要与别的同学,同事分工完成工作,如果没有注释的引导,理解起来将困难重重,注释可以帮助理解代码逻辑,促进团队协作提高可读性。

  3. 代码结构优化,在编写代码时,if - else 多层嵌套容易使代码结构变得复杂且难以理解,尽量不使用使用if-else多层嵌套,像一些有着相同结果的分支语句可以合并,将它们合并能有效简化代码结构,这样代码变得更加简洁明了,提高了代码的可维护性。

五、总结

  经过这一次电梯作业,我学会了Java中的许多知识点,了解了它与C语言的不同之处。写电梯调度算法极大地锻炼了我的逻辑思维,在反复编写、调试代码的过程中,我不仅学习,掌握了知识,也激发了我对于Java的学习热情,每一次修改改进我都会收获快乐。我也清楚认识到自己的不足,在代码规范和注释方面尤其是变量命名,做得还远远不够。在以后的学习中,我将进一步学习算法和规范书写代码,成为一个技术大佬。这次学习经历不仅是知识的积累,更是我向美好生活前进的一大步。

posted @ 2025-04-20 17:55  祖建明  阅读(19)  评论(0)    收藏  举报