面向对象程序设 一 第一次总结性Blog
一、前言
二、设计与分析
第一次电梯题目的设计与分析
题目要求: 设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
解决思路:用正则表达式处理输入数据,将输入数据分为一个电梯内队列,应该电梯外队列,然后用电梯调度算法(简化版LOOK算法)(每次到楼层或者准备出发前,电梯就会看看内部队列和外部两个队列(上行、下行)的 “排头” 请求。要是内部队列有更近的目标,就优先处理;要是外部队列的请求更合适,就调整方向过去。通过不断比较队列头的请求楼层,判断电梯该保持当前方向,还是得掉头,同时决定这层楼需不需要停稳开门接人),分别比较两个队列的头,判断不同情况的方向改变,以及是否应该打开该楼层。
代码规模
第一次电梯代码规模如下图。

分析:
由于我将所有的功能全部写进了Elevator中导致Elevator 代码规模大、逻辑复杂、注释过少,维护难度高;Main 相对代码规模小、逻辑简单些,注释较合理,维护难度低一些。 后续可考虑对 Elevator 进行重构,拆分复杂方法、增加注释等提升代码质量。
类图设计:
第一次电梯的类图设计如下图。

类的具体设计
Main: 主类,从启动程序开始,负责接收用户输入的数据,再把这些数据按照规则读入并处理。同时,创建电梯对象、初始化相关参数。
Directin: 是个枚举类型,专门用来定义电梯的运行状态,这样不仅代码看着一目了然,后续要是需要调整或扩展方向逻辑,改起来也方便。
Elevator: 电梯类,完成Main中所需要的各种功能,Main类接收到的数据要怎么处理、电梯该怎么响应乘客请求,不管是计算楼层移动、管理内外请求队列,还是根据调度算法调整运行方向,这些功能都由这个类实现,设计的有问题,复杂度也很高。
复杂度分析
第一次电梯的Source Monitor分析结果如下。

分析:
第二次电梯题目的设计与分析
题目要求: 对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类.相相对于上一题对于类的设计有了明确要求,必须拆分职责,遵循单一职责原则。
解决思路:设计电梯类(只专注处理电梯本身的动作,比如楼层升降、开关门这些基础操作)、乘客请求类(专门记录每个乘客从哪层出发、要到哪层,把请求细节单独管起来)、队列类(负责管理乘客请求的排队顺序,入队、出队、查看队列状态)以及控制类(根据电梯状态、请求队列情况,决定下一步该怎么调度电梯)的相应功能以及功能。
代码规模
第二次电梯代码规模如下图。

分析
总体而言,Controller和 Main代码复杂度较高,逻辑相对复杂且缺乏注释,维护难度大;而 Elevator、ExternalRequest、Requestqueue 代码相对简单,但均存在无注释问题。后续可考虑为这些文件添加注释,并对复杂度高的代码进行优化重构,提高代码的可读性和可维护性。
类图设计:
第二次电梯的类图设计如下图。

类的具体设计
Main:主要负责读取用户输入的数据。它需要解析输入格式,比如用正则表达式拆分每一条乘客请求,创建Elevator、RequestQueue等所需的类实例,同时,它还会调用其他类的方法,串联起数据处理和业务执行的流程。
Direction:枚举类用于定义电梯的运行方向,包含 “上行”“下行”“静止” 三种状态。程序中其他类在判断电梯移动方向、执行调度逻辑时,都会引用这个枚举类,保证方向定义的一致性和准确性。
State:枚举类用来记录电梯的运行状态,涵盖 “运行中”“停止且开门”“空闲等待” 等状态。
Elevator:封装了电梯的核心属性与操作。属性方面,包含最大楼层数、最小楼层数、当前楼层、承载人数等基本信息;操作方法上,实现了楼层升降、开关门等功能。
ExternalRequest:专注于处理电梯外部的乘客请求,每个实例对应一个来自某楼层的上行或下行请求,包含请求楼层、请求方向等信息。
RequestQueue:负责管理电梯内、外的乘客请求队列。它内部维护两个独立的队列,一个存储电梯内部乘客的目的楼层请求,另一个存储电梯外部的上行和下行请求。
Controller:是电梯调度逻辑的核心实现。它会实时获取Elevator类的当前状态和楼层信息,以及RequestQueue类中的所有请求数据,然后依据简化版 LOOK 算法,判断电梯的运行方向是否需要改变,决定在哪些楼层停靠并处理相应请求。
复杂度分析
第二次电梯的Source Monitor分析结果如下。

分析:
第三次电梯题目的设计与分析
题目要求: 对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类:就是要加一个乘客类(Passenger),设计类的时候,还是得遵守单一职责原则。必须设计的类有电梯类、乘客类、队列类,还有控制类。和第二次题目比起来,就是用乘客类把 ExternalRequest 给替换掉。
解决思路:新增一个 Passenger 类,用它来代表电梯里的乘客和在外面等着坐电梯的乘客。这个类能把乘客的各种信息和需求都装进去,这样不管是电梯内的队列,还是电梯外的队列,都能用这个 Passenger 类来处理。
代码规模
第三次电梯代码规模如下图。

分析
我延用的第二次题目集的类设计的,只是改了一下输入的格式,这个就类似于第二次的分析结果。
类图设计:
第三次电梯的类图设计如下图。

类的具体设计
Main:主要负责读取用户输入的数据。它需要解析输入格式,比如用正则表达式拆分每一条乘客请求,创建Elevator、RequestQueue等所需的类实例,同时,它还会调用其他类的方法,串联起数据处理和业务执行的流程。
Direction:枚举类用于定义电梯的运行方向,包含 “上行”“下行”“静止” 三种状态。程序中其他类在判断电梯移动方向、执行调度逻辑时,都会引用这个枚举类,保证方向定义的一致性和准确性。
State:枚举类用来记录电梯的运行状态,涵盖 “运行中”“停止且开门”“空闲等待” 等状态。
Elevator:封装了电梯的核心属性与操作。属性方面,包含最大楼层数、最小楼层数、当前楼层、承载人数等基本信息;操作方法上,实现了楼层升降、开关门等功能。
Passenger:这个类主要记录乘客输入的信息,比如乘客是从哪一层进入电梯的,要去的是哪一层,这些信息都由它来保管。
RequestQueue:这个类里面有两个队列。一个队列专门记录电梯里面乘客要去的楼层信息,另一个队列则记录电梯外面等待的乘客的信息,通过这两个队列来管理不同位置的乘客请求。
Controller:这个类是实现电梯运行算法的关键。它会根据电梯当前的状态、所在楼层,以及乘客的请求信息,运用电梯调度算法(简化版LOOK算法)来决定电梯接下来该怎么运行,是往上走还是往下走,在哪一层该停下来开门。
复杂度分析
第三次电梯的Source Monitor分析结果如下。

分析:
和上一次分析相比,Contorller.determineDirection()复杂度从 12 升至 17 ,语句数从 17 变为 20 ,最大深度从 4 增加到 6 ,调用数从 12 跃至 32 ;Controller.removeRequest()复杂度从 17 未变,但语句数从 24 增加到 33 ,最大深度从 8 降到 7 ,调用数从 24 大幅增至 67 。这表明这些关键方法的复杂度在持续上升或虽有波动但仍处于较高水平,说明在电梯运行方向判定、请求移除等核心逻辑上,代码没有得到有效简化,反而愈发复杂。而上次复杂度较高的Controller.processRequests(),这次复杂度从 13 降至 5 ,语句数从 30 减为 10 ,说明在处理请求这部分逻辑上可能进行了一定优化,但整体来看,Controller类中方法复杂度依然参差不齐。
三、踩坑心得
对类设计原则理解不足
类与类关系构建失误
缺乏创新与突破
四、改进建议
五、总结
问题的理解和拆分能力得到提升
从一开始面对复杂的电梯调度问题无从下手,到后来学会把大问题拆解成 “请求处理”“方向判断”“楼层移动” 等小模块,逐个击破。这种化繁为简的思维方式,让你在后续处理其他复杂任务时更有条理。
类的设计能力的提升
初期因不懂 “单一职责原则”,把代码全塞在一个类里;到后来意识到类要各司其职,比如电梯类只负责电梯运行,队列类专门管理请求。这种对编程规范和设计模式的理解,是写好代码的基础。
心态与学习方法
从一开始急于求成、盲目写代码,到后来明白要先规划再动手;从死磕问题到学会查阅资料、参考示例。这种心态和学习方法的转变,能让我在未来的学习中少走弯路。

浙公网安备 33010602011771号