对这次大作业中的电梯问题的总结性blog
- 前言
在这三次的作业的电梯问题中,时间适中但是由于之前没有实操过这类的迭代的代码导致上手的时候还是出现了许多的问题以及由于经验不足导致的代码过于复杂和迭代性差且难以更新以至于后两次作业几乎是重新编写的,并且由于各种问题导致我对于这次题目的要求理解不到位使得我的代码出现了很多的问题导致没有一次的代码是完全正确的。
设计与分析
- 第一次电梯问题的类图

-
对类的分析:
由于第一次上手编写难度较大的代码,我的准备工作做的并不完善,实际上有很多我没有考虑到的地方以至于我的第一次编写的代码缺陷非常多,非常不利于未来的迭代以及修改,第一次实验中我的代码一共只有两个类 -
Main类:
对输入的数据进行处理 -
Elevator类:
用于对最大最小楼层,行进方向,内外部的输入进行存储以及判断和修改行进方向和上下楼的处理
使用SourceMointor的分析结果:

根据这张图表很容易的发现问题所在:
1.平均复杂度较高:平均复杂度(Average Complexity)为 6.00 ,说明整体代码逻辑复杂程度偏高。这会导致代码理解困难,开发人员接手维护时,需要花费更多时间梳理逻辑,增加了学习成本和出错风险。
2.最大复杂度突出:Elevator.run() 方法的最大复杂度(Maximum Complexity)达到 23 。高圈复杂度意味着该方法内包含大量条件判断(如if - else)、循环等控制结构,使代码的执行路径错综复杂,不仅难以理解,而且修改时极易引发连锁反应,产生新的问题。同时,单元测试覆盖所有逻辑路径也变得极具挑战性。
3. 方法语句数偏多:平均每个方法的语句数(Average Statements per Method )为 10.11 ,而最复杂方法 Elevator.run() 的行数(Line Number of Most Complex Method )达到 114 。过长的方法往往意味着功能过于集中,违背了单一职责原则,不利于代码的复用和=维护。当需要修改或扩展功能时,在大量代码中定位相关逻辑会耗费大量时间。
4.类的方法数量不均衡:每个类的平均方法数(Methods per Class )为 4.50 ,但结合复杂度过高的情况,可能存在部分类方法职责划分不清晰,某些类承担了过多功能,导致方法数量和复杂度都不合理。
5. 最大代码块深度较深:最大块深度(Maximum Block Depth )为 5 ,最深代码块行号(Line Number of Deepest Block )为 61 ,表明代码中存在较深层的嵌套结构,如多层循环嵌套或条件语句嵌套。深层嵌套会使代码逻辑的可读性急剧下降,程序执行流程难以追踪,调试和排查问题变得困难。
6.平均代码块深度不理想:平均块深度(Average Block Depth )为 3.17 ,说明整体代码存在一定程度的嵌套情况,虽然平均数值未达特别严重程度,但仍会影响代码的清晰度和可维护性。
由于第一次编写这类的相关的代码使用了太多重复的方法,这是我这段代码的不足之处并且由于许多的不知名原因导致我这段代码虽然在测试时的输出和给的输出样例是一样的但是还是没有通过这次的实验
- 第二次电梯问题的类图:

- 对类的分析:
对于这次实验的代码来说我原本的设想就是去设置一个专门的类用来进行对电梯运行的控制,但是由于参数引用和代码行数的问题,我最后把运行的开关以及输入和输出要求放在了电梯的类里而不是控制的类中,我的代码中一共有五个类 - Main类:
用来处理输入外部的请求和数据 - Controller类:
用于判断与执行电梯上下楼层操作的类 - Elevator类:
用于设置电梯相关信息以及楼层相关信息以及任务列表的类 - RequestQueue类:
用于处理外部与内部的楼层信息的类 - Floor类:
关于楼层的信息的处理以及行进方向的处理
使用SourceMointor的分析结果:

可以看出代码还是存在不少问题的,
1.方法复杂度高Controller.processRequests()方法:最大复杂度达 23,圈复杂度高意味着逻辑分支众多,可能存在大量if - else、循环、switch等嵌套逻辑,可读性和可维护性差,调试和修改易出错,单元测试覆盖难度大。
2.复杂度不均衡:平均复杂度 2.79 ,但存在个别复杂度过高方法,说明代码中方法复杂度差异大,结构不够合理。
方法语句量不合理
3.Controller.processRequests()方法:行号达 156,远高于平均每个方法 4.96 条语句的水平,功能可能过于集中,违背单一职责原则,代码冗长,理解和维护困难。
4.最大代码块深度深:最大块深度为 6 ,深层嵌套(如多层if - else嵌套、循环嵌套)使代码逻辑结构混乱,执行流程难以追踪,易产生逻辑错误,且修改时牵一发而动全身。
5.平均代码块深度有提升空间:平均块深度 2.47,说明整体代码存在一定嵌套情况,虽未达严重程度,但仍需优化以提升代码清晰度。
- 第三次电梯问题的类图

- 对类的分析:
对这次的实验我只是根据题目给出的类图进行代码的编写,把所有的控制相关的操作全部集成到了我的Controller类中然后把内外输入都放在Passenger类中方便后续的调用,并且把输入放进内外两个链表中还加入了两个枚举类state和Direction用于判断电梯的状态 - Main类:
用来处理输入外部的请求和数据 - Controller类:
将所有有关操作,电梯移动,判断电梯方向以及改变方向等汇总在这一个类中 - Elevator类:
用于设置电梯相关信息以及楼层相关信息以及任务列表的类 - RequestQueue类:
用于处理外部与内部的楼层信息并加以区分和调用的类 - Passenger类:
表示乘客,包含出发楼层和目标楼层属性,以及相关的访问和设置方法。
使用SourceMointor的分析结果:

1. 平均复杂度:平均复杂度(Average Complexity)为 3.82 ,整体处于中等水平,但仍有优化空间。较高的平均复杂度会增加新开发者理解代码逻辑的难度,排查问题和进行功能扩展时也更易出错。
2. 最大复杂度:Controller.processRequests() 方法的最大复杂度(Maximum Complexity)达到 12 。这表明该方法内部逻辑分支较多,可能存在大量条件判断、循环嵌套等情况。高复杂度使方法的执行路径难以追踪,修改时容易引发连锁反应,而且编写单元测试来覆盖所有逻辑路径会非常困难。
3. 平均语句数:平均每个方法的语句数(Average Statements per Method )为 4.37 ,看似不算多,但最复杂方法 Controller.processRequests() 的行数(Line Number of Most Complex Method )达到 161 。说明该方法代码量远超平均水平,功能可能过度集中,违背了单一职责原则,不利于代码的复用和维护。当需要修改或扩展功能时,在大量代码中定位相关逻辑会耗费大量时间。
4. 类的方法数量:每个类的平均方法数(Methods per Class )为 11.67 ,方法数量较多。可能存在类的职责划分不够清晰的情况,导致一个类承担了过多功能,增加了类的复杂性。
5. 最大代码块深度:最大块深度(Maximum Block Depth )为 6 ,最深代码块行号(Line Number of Deepest Block )为 167 ,说明代码中存在较深层的嵌套结构,如多层条件语句或循环嵌套。深层嵌套会使代码逻辑变得混乱,可读性变差,程序执行流程难以理解,调试时也很难定位问题。
6. 平均代码块深度:平均块深度(Average Block Depth )为 2.13 ,虽然数值不算特别高,但也反映出整体代码存在一定程度的嵌套情况,对代码的清晰度有一定影响,需要进一步优化以提升代码质量。
踩坑心得:
这段将对我编写代码过程中碰到的问题以及困难进行分析
1. 在第一次电梯代码中我使用的时ArrayList来进行对内外部数据的存储和读取并使用if语句来判断到达条件时跳出循环的操作但是由于各种原因在运行时会显示超时,后续改为提前存储数组内的数据数量判断最大循环次数后运行超时变成了答案错误然后一直也没改对
2.进行编写前我没能正确的理解题目的意思,原先我写的是优先处理最近的楼层但后来对题目给出的例子仔细琢磨了一下之后发现题目的要求是方向上的优先,即对内外两个输入列表的最前面的输入进行对比且没处理完一个输入之后便删除第一个的输入在进行下一步的比对和判断。
3.在进行对重复输入和删除输入的操作中有不少问题,我原先处理重复输入时只判断相邻的两个输入是不是完全相同若是就删除前一个然后再进入下一位判断,但是其中如果有三个连着的重复输入的话进入下一位的判断时容易忽略其中的一个造成两次停在一个楼层并且开门的情况,后经过修改修正了这个问题,我的删除输入的操作原本是先把所到楼层和第一个输入进行比对如果正确的话就将输入队列中的该楼层全部删除但是这导致了如果有不是连续输入的两个楼层时会将后面的楼层也删除导致电梯不会再往下运行导致错误后经过修改之后电梯能正确的按照要求运行但是还是会显示答案错误
4.第一次进行编写时没有整合同一种类的操作到一个类里导致代码过于复杂和可读性很差还导致维护和更新迭代十分困难
代码不足以及可优化处:
1.对于我的代码我认为可以更精简方法和将效果相同或类似的代码进行再次的分类。
2.代码的注释太少交给其他人短时间内看不懂代码。
3.代码的循环和判断的嵌套过多,可以检查并简化代码中的深层嵌套结构,通过提前返回、使用设计模式(如状态模式、策略模式)等方式,优化代码逻辑,提升代码的清晰度和可维护性。
4.在一个方法中的功能过多,可以适当的分散方法的职能重点对 Controller.processRequests() 方法进行拆分,按照功能将其划分为多个小方法,如将请求处理逻辑、方向判断逻辑、停靠判断逻辑等分别提取出来,降低单个方法的复杂度和代码行数。
总结:
三次作业中的电梯问题给了我启发,在后面的迭代的大作业中我应该尤其注意代码的可迭代维护性和可读性,面向对象的编程和之前的c语言中的编程有许多的不同,现在应该更多的关注怎么让代码在其他人的手上也能正常准确的运行。
在对代码进行编写时我也同样的发现我对一些基础知识的运用并不娴熟,之后的练习我也会注意这方面的
这次的渐进式练习对检验我们代码的掌握程度非常好,并且让我们能更好的掌控自己编写的代码
第一次代码:
点击查看代码
import java.util.LinkedList;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Main
{
public static void Enter(String in, RequestQueue queue)
{
// 重复的条件检查
if (in.startsWith("<") && in.endsWith(">"))
{
// 处理普通楼层
if (in.indexOf(',') == -1)
{
String numStr = in.substring(1, in.length()-1);
try {
int num = Integer.parseInt(numStr);
queue.addLink(new Floor(num));
} catch (Exception e) {}
}
// 处理带方向的楼层
else
{
String content = in.substring(1, in.length()-1);
String[] parts = content.split(",");
if (parts.length == 2)
{
try {
int num = Integer.parseInt(parts[0]);
String dir = parts[1];
if (dir.equals("UP") || dir.equals("DOWN"))
{
queue.addLink(new Floor(num, dir));
}
}catch (Exception e){}
}
}
}
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int minfloor = input.nextInt();
int maxfloor = input.nextInt();
input.nextLine();
RequestQueue queue = new RequestQueue();
while (true)
{
String line = input.nextLine().trim();
if (line.equalsIgnoreCase("end"))
{
break;
}
Enter(line, queue);
}
queue.ModifyInnerList();
queue.ModifyOutterList();
Elevator elevator = new Elevator(minfloor, maxfloor);
Controller controller = new Controller(elevator, queue);
for (Integer floor : queue.InnerLink)
{
elevator.addInnerRequest(floor);
}
for (Floor floor : queue.OutterLink)
{
if (floor.getdirection().equals("UP"))
{
elevator.addUpRequest(floor.getFloor());
}
else
{
elevator.addDownRequest(floor.getFloor());
}
}
elevator.run();
}
}
class Elevator
{
private int minfloor;
private int maxfloor;
private int nowfloor;
private int actionState; // 1=UP, 2=DOWN
private LinkedList<Integer> Inrequest = new LinkedList<>();
private LinkedList<Integer> upRequest = new LinkedList<>();
private LinkedList<Integer> downRequest = new LinkedList<>();
public Elevator(int minfloor, int maxfloor)
{
this.minfloor = minfloor;
this.maxfloor = maxfloor;
this.nowfloor = 1;
this.actionState = 1;
}
public void addInnerRequest(int floor)
{
if (floor >= minfloor && floor <= maxfloor)
{
Inrequest.add(floor);
}
}
public void addUpRequest(int floor)
{
if (floor >= minfloor && floor <= maxfloor)
{
upRequest.add(floor);
}
}
public void addDownRequest(int floor)
{
if (floor >= minfloor && floor <= maxfloor)
{
downRequest.add(floor);
}
}
public void run()
{
System.out.println("Current Floor: " + nowfloor + " Direction: " + (actionState == 1 ? "UP" : "DOWN"));
while (!(Inrequest.isEmpty() && upRequest.isEmpty() && downRequest.isEmpty()))
{
if (actionState == 1 && !hasHigher())
{
actionState = 2;
}
else if (actionState == 2 && !hasLower())
{
actionState = 1;
}
if (nowfloor == maxfloor && actionState == 1)
{
actionState = 2;
continue;
}
if (actionState == 1)
{
nowfloor++;
}
if (nowfloor == minfloor && actionState == 2)
{
actionState = 1;
continue;
}
if (actionState == 2)
{
nowfloor--;
}
System.out.println("Current Floor: " + nowfloor + " Direction: " + (actionState == 1 ? "UP" : "DOWN"));
boolean stop = false;
if (Inrequest.contains(nowfloor)&&Inrequest.get(0)==nowfloor)
{
Inrequest.remove(Integer.valueOf(nowfloor));
stop = true;
}
if (actionState == 1 && upRequest.contains(nowfloor) && upRequest.get(0)==nowfloor)
{
upRequest.remove(Integer.valueOf(nowfloor));
stop = true;
}
else if (actionState == 2 && downRequest.contains(nowfloor) &&downRequest.get(0)==nowfloor)
{
downRequest.remove(Integer.valueOf(nowfloor));
stop = true;
}
if(stop)
{
System.out.println("Open Door # Floor " + nowfloor);
System.out.print("Close Door");
if(upRequest.isEmpty()&&downRequest.isEmpty()&&Inrequest.isEmpty())
{
return ;
}
else
{
System.out.printf("\n");
}
}
}
}
private boolean hasHigher()
{
for (int floor : Inrequest)
{
if (floor > nowfloor)
{
return true;
}
}
for (int floor : upRequest)
{
if (floor > nowfloor)
{
return true;
}
}
return false;
}
private boolean hasLower()
{
for (int floor : Inrequest)
{
if (floor < nowfloor)
{
return true;
}
}
for (int floor : downRequest)
{
if (floor < nowfloor)
{
return true;
}
}
return false;
}
}
class Controller
{
Elevator elevator;
RequestQueue queue;
public Controller(Elevator elevator, RequestQueue queue)
{
this.queue = queue;
this.elevator = elevator;
}
public RequestQueue getQueue()
{
return queue;
}
public Elevator getElevator()
{
return elevator;
}
public void move()
{
elevator.run();
}
}
class Floor
{
int floor;
String direction;
public Floor(int floor)
{
this.floor = floor;
this.direction = "NULL";
}
public Floor(int floor, String direction)
{
this.floor = floor;
this.direction = direction;
}
public int getFloor()
{
return floor;
}
public String getdirection()
{
return direction;
}
}
class RequestQueue
{
LinkedList<Integer> InnerLink = new LinkedList<>();
LinkedList<Floor> OutterLink = new LinkedList<>();
public RequestQueue()
{
}
public void ModifyInnerList()
{
if (InnerLink.size() < 2)
{
return;
}
for (int i = 1; i < InnerLink.size(); )
{
if (InnerLink.get(i).equals(InnerLink.get(i - 1)))
{
InnerLink.remove(i);
}
else
{
i++;
}
}
}
public void ModifyOutterList()
{
if (OutterLink.size() < 2)
{
return;
}
for (int i = 1; i < OutterLink.size(); )
{
Floor current = OutterLink.get(i);
Floor previous = OutterLink.get(i - 1);
if (current.floor == previous.floor && current.direction.equals(previous.direction))
{
OutterLink.remove(i);
}
else
{
i++;
}
}
}
public void addLink(Floor floor)
{
if (floor.direction.equals("NULL"))
{
InnerLink.addLast(floor.floor);
}
else
{
OutterLink.addLast(floor);
}
}
}
第二次代码:
点击查看代码
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
enum Direction
{
UP,
DOWN,
IDLE
}
enum State
{
MOVING,
STOPPED
}
class ExternalRequest {
int floor;
Direction direction;
public ExternalRequest(int floor, Direction direction) {
this.floor = floor;
this.direction = direction;
}
public int getFloor() {
return floor;
}
public Direction getDirection() {
return direction;
}
}
public class Mpin {
public static void Enter(String in, RequestQueue queue) {
if (in.startsWith("<") && in.endsWith(">")) {
if (in.indexOf(',') == -1) {
String numStr = in.substring(1, in.length() - 1);
int num = Integer.parseInt(numStr);
queue.addInternalRequest(num);
} else {
String content = in.substring(1, in.length() - 1);
String[] parts = content.split(",");
if (parts.length == 2) {
int num = Integer.parseInt(parts[0]);
String dir = parts[1];
Direction direction = Direction.IDLE;
if (dir.equals("UP")) {
direction = Direction.UP;
} else if (dir.equals("DOWN")) {
direction = Direction.DOWN;
}
queue.addExternalRequest(num, direction);
}
}
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int minFloor = input.nextInt();
int maxFloor = input.nextInt();
input.nextLine();
RequestQueue queue = new RequestQueue();
int i = 0;
while (i < 300) {
String line = input.nextLine().trim();
if (line.equalsIgnoreCase("end")) {
break;
}
Enter(line, queue);
i++;
}
queue.ModifyInnerList();
queue.ModifyOutterList();
Elevator elevator = new Elevator(minFloor, maxFloor);
Controller controller = new Controller(elevator, queue);
controller.processRequests();
}
}
class Elevator {
State state;
Direction direction;
private final int minFloor;
private final int maxFloor;
private int currentFloor = 1;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.state = State.STOPPED;
this.direction = Direction.UP;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getMaxFloor() {
return maxFloor;
}
public int getMinFloor() {
return minFloor;
}
public boolean isValidFloor(int floor) {
return floor >= minFloor && floor <= maxFloor;
}
}
class Controller {
Elevator elevator;
RequestQueue queue;
public Controller(Elevator elevator, RequestQueue queue) {
this.queue = queue;
this.elevator = elevator;
}
public void moveUp() {
elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
}
public void moveDown() {
elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
}
public void processRequests() {
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.direction);
while (!(queue.externalRequests.isEmpty() && queue.internalRequests.isEmpty())) {
// Check boundaries and reverse direction if needed
if (elevator.getCurrentFloor() == elevator.getMaxFloor()) {
elevator.direction = Direction.DOWN;
} else if (elevator.getCurrentFloor() == elevator.getMinFloor()) {
elevator.direction = Direction.UP;
}
// Sort internal requests based on current direction
if (elevator.direction == Direction.UP) {
Collections.sort(queue.internalRequests);
} else {
Collections.sort(queue.internalRequests, Collections.reverseOrder());
}
// Move elevator
if (elevator.direction == Direction.UP) {
moveUp();
} else {
moveDown();
}
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.direction);
elevator.state = State.MOVING;
// Process all internal requests at current floor (regardless of direction)
boolean internalStop = false;
Iterator<Integer> internalIter = queue.internalRequests.iterator();
while (internalIter.hasNext()) {
int floor = internalIter.next();
if (floor == elevator.getCurrentFloor()) {
internalIter.remove();
internalStop = true;
}
}
// Process external requests matching current direction
boolean externalStop = false;
Iterator<ExternalRequest> externalIter = queue.externalRequests.iterator();
while (externalIter.hasNext()) {
ExternalRequest req = externalIter.next();
if (req.floor == elevator.getCurrentFloor() && req.direction == elevator.direction) {
externalIter.remove();
externalStop = true;
}
}
// Handle stopping logic
if (internalStop || externalStop) {
elevator.state = State.STOPPED;
System.out.println("Open Door # Floor " + elevator.getCurrentFloor());
System.out.print("Close Door");
if (queue.internalRequests.isEmpty() && queue.externalRequests.isEmpty()) {
return;
} else {
System.out.println();
}
}
// Check for remaining requests in current direction
boolean hasRequests = checkRequestsInDirection();
if (!hasRequests) {
// Reverse direction and rescan all requests
elevator.direction = (elevator.direction == Direction.UP) ? Direction.DOWN : Direction.UP;
if (!queue.internalRequests.isEmpty() || !queue.externalRequests.isEmpty()) {
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.direction);
continue; // Re-process without moving
}
}
}
}
private boolean checkRequestsInDirection() {
if (elevator.direction == Direction.UP) {
return queue.internalRequests.stream().anyMatch(f -> f > elevator.getCurrentFloor()) ||
queue.externalRequests.stream().anyMatch(req ->
req.direction == Direction.UP && req.floor > elevator.getCurrentFloor());
} else {
return queue.internalRequests.stream().anyMatch(f -> f < elevator.getCurrentFloor()) ||
queue.externalRequests.stream().anyMatch(req ->
req.direction == Direction.DOWN && req.floor < elevator.getCurrentFloor());
}
}
}
class RequestQueue {
LinkedList<Integer> internalRequests = new LinkedList<>();
LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
public void addInternalRequest(int floor) {
internalRequests.add(floor);
}
public void addExternalRequest(int floor, Direction direction) {
externalRequests.add(new ExternalRequest(floor, direction));
}
public void ModifyInnerList() {
if (internalRequests.size() < 2) {
return;
}
for (int i = 1; i < internalRequests.size(); ) {
if (internalRequests.get(i).equals(internalRequests.get(i - 1))) {
internalRequests.remove(i);
} else {
i++;
}
}
}
public void ModifyOutterList() {
if (externalRequests.size() < 2) {
return;
}
for (int i = 1; i < externalRequests.size(); ) {
ExternalRequest current = externalRequests.get(i);
ExternalRequest previous = externalRequests.get(i - 1);
if (current.getFloor() == previous.getFloor() && current.getDirection() == previous.getDirection()) {
externalRequests.remove(i);
} else {
i++;
}
}
}
}
浙公网安备 33010602011771号