第一次Blog作业

前言:
本学期通过三次电梯调度题目集的实践,我对Java面向对象编程有了更深刻的理解。第一次题目集让我掌握了基础语法和简单逻辑实现,建立了程序框架;第二次题目集增加了请求处理的复杂性,促使我深入思考状态管理和调度算法;第三次题目集则要求更高的系统设计能力,需要合理划分类职责并优化整体架构。

在知识运用方面,我学会了如何将现实问题抽象为类与对象,比如用Elevator类封装电梯属性和行为,用RequestQueue管理请求队列。通过这三次实践,我不仅巩固了循环、条件判断等基础语法,更重要的是培养了模块化设计思维,理解了封装的重要性。难度递进的设计让我逐步掌握了从简单功能实现到复杂系统构建的能力提升路径。

这些练习让我认识到,好的程序设计需要兼顾功能实现和代码结构。从最初的简单功能堆砌,到现在能有意识地运用设计原则,我的编程思维和工程能力都得到了显著提升。这种循序渐进的学习方式,有效地帮助我将理论知识转化为实践能力。

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

类与属性设计:Passenger类仅存储乘客的源楼层和目标楼层,无业务逻辑。
RequestQueue管理两类请求队列:externalRequests(外部请求,存储 Passenger对象)和 internalRequests(内部请求,存储目标楼层)。
Elevator 类负责电梯的当前位置、运行方向(上行、下行、静止)及楼层范围限制。
Controller作为调度中枢,协调电梯移动和请求处理。

请求处理方法:外部请求(<源楼层, 目标楼层>)存入 externalRequests,处理完成后将目标楼层加入 internalRequests。
内部请求(<楼层>)直接存入 internalRequests,代表电梯内乘客的目标楼层。

调度逻辑方法:优先级:优先处理 internalRequests(电梯内乘客请求),再处理 externalRequests(外部召唤)。
电梯移动:根据目标楼层动态调整方向(direction),逐层移动并实时输出当前楼层。

运行与状态管理:电梯通过 direction 状态(1/-1/0)控制运行方向,确保不超出 minFloormaxFloor 范围。
Controller` 监听请求队列,按规则调度电梯,直至所有请求完成。

主类逻辑:解析输入数据,区分内外请求,调用 Controller 添加请求。
输入 "end" 后触发 processRequests(),开始调度。
心得:SRP 优势:各类职责清晰,如 Elevator 仅关注移动,RequestQueue 专注队列管理,便于维护和扩展。
调度效率:内部请求优先减少乘客等待时间,符合现实场景。
输入灵活性:兼容 <a,b><a> 格式,鲁棒性强。

整体设计简洁高效,严格满足题目要求,适合进一步优化或扩展多电梯场景。

第二次作业:
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(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. 外部请求类(ExternalRequest)
    在本次设计中,外部请求直接使用 Passenger 类表示,包含两个核心属性:
    -sourceFloor(乘客发起请求的楼层)
  • targetFloor(乘客目标楼层)
    初职责:仅存储请求数据,不处理逻辑,符合单一职责原则(SRP)。
  1. 电梯类(Elevator)
    属性:
  • currentFloor(当前楼层)
  • direction(运行方向:1上行,-1下行,0静止)
  • minFloormaxFloor(楼层限制)
    方法:
  • move():根据 direction 更新当前楼层。
  • setDirection():调整运行方向。
    职责:仅控制电梯物理移动,与请求逻辑解耦。
  1. 请求队列类(RequestQueue)
    属性:
  • externalRequestsQueue<Passenger>(外部请求队列)
  • internalRequestsQueue<Integer>(内部目标楼层队列)
    方法:
  • addExternalRequest() / addInternalRequest():分别添加内外请求。
  • getNextRequest():按优先级(内部>外部)提供下一个请求。
    职责:高效管理请求队列,确保调度顺序。
  1. 控制类(Controller)
    属性:绑定 ElevatorRequestQueue 实例。
    核心方法:
  • processRequests():循环处理队列,调用电梯移动。
  • moveToFloor():控制电梯逐层移动至目标楼层。
    职责:协调电梯与队列,实现调度逻辑(如外部请求处理后自动加入内部队列)。
  1. 主类(Main)
    逻辑流程:
  2. 读取输入楼层范围(minFloor, maxFloor)。
  3. 解析每行请求(<a,b>为外部请求,<a>为内部请求)。
  4. 调用 Controller 添加请求,输入 "end" 后启动调度。
    职责:处理输入/输出,初始化系统。
    关键设计特点:
  5. SRP 贯彻:每个类仅负责单一功能(如 Elevator 不管队列,RequestQueue 不管移动)。
  6. 请求优先级:内部请求优先处理,减少乘客等待时间。
  7. 扩展性:可轻松新增功能(如多电梯、容量限制)。
  8. 输入兼容性:支持灵活的外部/内部请求格式。

第三次题目:
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类。
电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队
尾)
注意:本次作业类设计必须符合如上要求(包含但不限于设计电梯类、乘客类、队列类以及控制类),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次及第二次电梯程序提交到本次题目中测试)。
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<请求源楼层,请求目的楼层>,其中,请求源楼层表示乘客发起请求所在的楼层,请求目的楼层表示乘客想要到达的楼层。
当输入“end”时代表输入结束(end不区分大小写)。

  1. 核心类与职责划分
    Passenger:仅存储乘客的源楼层和目标楼层,无业务逻辑,符合单一职责原则(SRP)。
    Elevator:管理电梯的当前位置、运行方向(上行/下行/静止)和楼层限制,仅负责物理移动。
    RequestQueue:维护两个队列:
    externalRequests:存储外部请求(Passenger 对象)。
    internalRequests:存储内部目标楼层(Integer)。
    Controller:协调电梯和队列,实现调度逻辑(如优先级处理、请求转换)。
    Main:处理输入/输出,初始化系统。
  2. 关键设计特点
  3. 单一职责原则(SRP)
    • 每个类仅完成一项核心功能(如 Elevator 不管队列,RequestQueue 不管移动)。
  4. 请求优先级
    内部请求优先:减少电梯内乘客的等待时间。
    外部请求转换:处理完外部请求后,自动将其目标楼层加入内部队列。
  5. 输入灵活性
    • 支持 <a,b>(外部请求)和 <a>(内部请求)两种格式。
  6. 电梯移动逻辑
    -通过 direction(1/-1/0)控制方向,逐层移动并实时输出状态。
  7. 调度流程
  8. 输入阶段
    • 解析每行请求,区分内外请求并存入队列。
  9. 处理阶段(Controller.processRequests()
    步骤1:优先从 internalRequests 取出目标楼层,移动电梯至该楼层。
    步骤2:若无内部请求,则处理 externalRequests
    • 先移动至乘客的源楼层。
    • 将该乘客的目标楼层加入内部队列。
  10. 终止条件:所有请求处理完毕(队列为空)。
  11. 扩展性*
  • 新增功能:如电梯容量限制、多电梯协作,只需修改 ControllerRequestQueue
  • 日志/统计:可轻松添加运行时间、乘客等待时间等监控功能。
    总结
    该设计通过职责分离和优先级调度,实现了高效、清晰的电梯控制逻辑,完全符合题目要求,且易于维护和扩展。

心得:通过三次电梯调度程序的迭代设计,我深刻体会到单一职责原则(SRP)的重要性——每个类只专注一项任务,代码更易读、易维护。第一次设计时,逻辑混杂导致调试困难;第二次引入队列后,调度效率提升;第三次彻底分离内外请求,并优化优先级处理,最终实现了清晰高效的调度逻辑。
最大的收获是模块化思维:将复杂问题拆解为独立模块(如电梯移动、请求队列、控制调度),再通过接口协同工作。这不仅降低了开发难度,也为后续扩展(如多电梯、超载处理)奠定了基础。
此外,输入/输出的严谨处理和边界条件测试让我意识到鲁棒性的关键。未来会继续用这种分治思想解决更复杂的系统设计问题。

posted on 2025-04-20 23:49  高涵子林  阅读(37)  评论(0)    收藏  举报

导航