阶段性题目集分析与总结

一、前言
至今为止共完成了七次题目集,其中自从题目集五开始,由面向过程设计逐渐转向面向对象设计。从五到七这三次题目集主要考察了面向对象程序设计的基本知识点如:
类的设计
数据域的封装
正则表达式的使用
单一职责原则
字符串函数的使用
ArrayList的使用
等等
相较于以上知识点,最难的还是将算法与面向对象的特点结合起来,设计出符合单一职责的面向对象程序。这三次题目集中这个特点最鲜明的莫过于是三次单部电梯调度以及迭代问题。
二、单部电梯调度的设计与分析
1.程序一
第一次程序仅仅用面向过程设计出来了符合题目的程序,未采用面向对象设计。而且源程序已丢失,所以在此跳过不分析。
2.程序二
(1)设计需求分析
程序二与程序一最大的区别在于添加了类设计需求,需要程序设计符合面向对象要求。类设计如下:

第二次电梯要求类设计以及输入查重,我认为较困难的是将功能拆分成不同类的单一功能职责,其中要求:

Direction枚举类:定义电梯运行方向,包括 UP(向上) 、DOWN(向下) 、IDLE(空闲) 三个枚举常量。
Elevator类
属性:有当前楼层 currentFloor(整数型)、运行方向 direction(Direction 枚举类型)、状态 state(State 枚举类型)、最大楼层 maxFloor(整数型)、最小楼层 minFloor(整数型) 。
方法:包含构造方法用于初始化最小和最大楼层;还有获取电梯实例、当前楼层、方向、状态等方法,以及设置这些属性的方法,还有判断楼层是否有效的方法。
State枚举类:定义电梯状态,有 MOVING(移动中)和 STOPPED(停止) 两个枚举常量。
ExternalRequest类
属性:请求楼层 floor(整数型)和请求方向 direction(Direction 枚举类型) 。
方法:构造方法用于初始化楼层和方向,还有获取楼层和方向的方法。
Controller类
属性:关联 Elevator 类实例和 RequestQueue 类实例。
方法:包含多个构造方法,以及获取和设置电梯、请求队列的方法,还有处理请求、确定方向、移动电梯、判断是否应停止等业务逻辑方法。
RequestQueue类
属性:内部请求 internalRequests(LinkedList 类型 ) 和外部请求 externalRequests(LinkedList 类型 ) 。
方法:构造方法,以及获取和设置内、外部请求列表的方法,还有添加内、外部请求的方法。
Main类:包含程序入口 main 方法(String args[] 为参数 ) 。
类关系
Elevator 类与 Direction 枚举类、State 枚举类关联,表明电梯具有运行方向和状态属性。
ExternalRequest 类与 Direction 枚举类关联,说明外部请求包含方向信息。
Controller 类与 Elevator 类、RequestQueue 类关联,用于控制电梯和处理请求队列。
RequestQueue 类与 ExternalRequest 类关联,用于管理外部请求列表。
完成后的程序分析如下:

(2)设计心得
在本次程序设计的时候有几个关键且有意思的点,我将引用部分源码来讲解。
刚开始的时候面对一个主程序,一团乱麻,不知道如何将它拆分。后来仔细研读了类图,发现秘诀就在于俄罗斯套娃————大类套小类。比如控制类,它包含了请求类和电梯类,而请求类里面又有两个内部类————队列类。
只要层层递进,就能设计出符合题目的面向对象程序。
算法设计
因为算法是在程序一就设计出来的,而程序一跳过没有讲,所以在这里讲讲,后面的算法都大同小异,无非加了一点细节。
算法其实很简单,只要认真读了题目集的附件大多数人都能写出来,无非是设置目标,处理,判断方向那一套。算法是我在纸上设计的,粘贴出来分享一下

一个有趣的点————一万楼
我的运行函数中经常出现类似的如下语句:
if(request.InternalRequest.get(0).floor>=elevator.currentFloor)
而1这个request.InternalRequest.get(0).floor,如果一个队列已经被清零,再调用的时候这个语句就会越栈报错,怎么办呢?常规的解决方法是在执行前加一个判断ArrayList是否为空的函数,但当时的我却没想着这么做,我脑子里只有一个朴素的想法————为空会报错,不为空不就行了吗?所有有了如下代码:
addExternalRequest(10000,Direction.UP);
addInternalRequest(10000,Direction.UP);
是的,我加了两个一万楼,这两个楼层永远不会被执行,为此我还修改了许多判定条件
楼层合法的判断函数:
static boolean isValidFloor(int floor) {
return (floor >= minFloor && floor <= maxFloor)||floor>9999;
}
运行结束的判断
if(request.InternalRequest.size()1&&request.ExternalRequest.size()1){
break;}
还有将这个10000楼排除在外的判断
if(request.InternalRequest.get(0).floor<=elevator.currentFloor&&request.InternalRequest.get(0).floor<=elevator.maxFloor)
(看着就复杂)
虽然这是个很坏的主意,但是在我一顿操作下,这个程序居然成功了!不过很快啊,这个bug程序就被制裁了,详情见程序三。
3.程序三
(1)设计需求分析
程序三主要修改了一下算法,使程序更模拟电梯运行,加了外部请求的目的地楼层。而且更新了类图如下:

枚举类
Direction:定义电梯运行方向,有 UP(向上)、DOWN(向下)、IDLE(空闲) 三个枚举常量。
State:定义电梯状态,包含 MOVING(移动中)和 STOPPED(停止) 两个枚举常量。
实体类
Elevator 类
属性:当前楼层 currentFloor(整型)、运行方向 direction(Direction 枚举类型)、状态 state(State 枚举类型)、最大楼层 maxFloor(整型)、最小楼层 minFloor(整型)。
方法:构造方法用于初始化最小和最大楼层;还有获取电梯实例、当前楼层、方向、状态等方法,以及设置这些属性的方法,还有判断楼层是否有效的方法。
Controller 类
属性:关联 Elevator 类实例和 RequestQueue 类实例。
方法:多个构造方法;获取和设置电梯、请求队列的方法;处理请求、确定方向、移动电梯、判断是否应停止等业务逻辑方法。
Passenger 类
属性:起始楼层 sourceFloor(整型,默认值为 null)、目的楼层 destinationFloor(整型,默认值为 null)。
方法:构造方法用于初始化起始楼层和目的楼层;获取和设置起始楼层、目的楼层的方法。
RequestQueue 类
属性:内部请求 internalRequests(类型为 LinkedList )和外部请求 externalRequests(类型为 LinkedList )。
方法:构造方法;获取请求队列实例,获取和设置内、外部请求列表的方法,添加内、外部请求的方法。
关系
关联关系:
Elevator 类与 Direction、State 枚举类关联,表明电梯具有运行方向和状态属性。
Controller 类与 Elevator 类、RequestQueue 类关联,用于控制电梯和处理请求队列。
RequestQueue 类与 Passenger 类关联,用于管理内、外部乘客请求列表。
Passenger 类的请求与 RequestQueue 类相关联。
类设计这一块儿变化不大,主要是算法稍有改动。将外部请求处理后把目的地的楼层插入到内部楼层请求最后。关于这个简单的需求我却走了点弯路,不过还是完工了,最终程序分析如下:

很明显相对于程序二还是复杂了那么一些的。
(2)设计心得
上次说的被制裁就是因为这个新算法,当我写完新程序并运行的时候,它出乎我的意料————超时了。我狐疑了一会儿,便想起来了我程序二最大的特色(bug)————一万楼!!!是的,我把目的地楼层插到了一万楼后面,它肯定会超时。最终还是老老实实地修改了代码,添加了判断是否为空的函数。
之前提到的那些代码修改后如下:
if(request.InternalRequest.isEmpty()&&request.ExternalRequest.isEmpty()){
break;}

if(!request.InternalRequest.isEmpty()&&request.InternalRequest.get(0).floor>=elevator.currentFloor)
最终还是完成了程序三的设计。
三、改进设计
** 1.注释**
身为一个懒蛋,我几乎不写注释,导致我的代码只有我能看懂(有时候我也看不懂)。在以后的程序设计中我尽量给关键代码写上注释。
2.复杂度
方法复杂度过高,造成的原因是我没有严格遵循单一职责设计,总是想让一个方法多办一点事情。在今后的面向对象程序设计中我严格遵循单一职责原则,简化方法。
** 3.使用正确的解决方案**
在程序出现问题时,要治根治本,不能只治本不治根。随着代码越来越复杂庞大,根出现问题会导致整个程序崩溃。
四、总结
1. 学习收获
(1)面向对象设计能力提升:通过三次电梯调度迭代开发,掌握了类拆分、数据封装、职责分离等核心思想,深刻体会到单一职责原则在降低代码耦合度中的重要作用。
(2)算法与设计模式的结合:在调度算法实现中,逐步学会将过程式逻辑封装到对象方法中,初步建立"状态驱动"的设计思维,为后续学习状态模式奠定基础。
(3)调试与问题定位能力:通过处理"一万楼"等边界问题,培养了异常场景分析能力,认识到临时方案的技术债务代价,促使形成稳健的编码习惯。

2. 待提升方向
(1)性能优化意识:优化各类算法,降低时间复杂度。
(2)代码简洁性管控:部分代码不符合单一职责要求,调用过多,功能太多,不符合可读性与简洁性。

3. 教学改进建议
能不能给实验提交系统加个复制粘贴啊?我眼睛要敲代码敲瞎了。

本阶段性学习通过单部电梯调用问题的实践,构建了面向对象设计的认知框架,培养了架构设计视野,为复杂系统开发奠定了坚实基础。

posted @ 2025-04-20 17:04  蜕秽浮尘  阅读(21)  评论(0)    收藏  举报