PTA5-7题集电梯题目全面解析以及总结

1. 前言

初识电梯
在2025/03/24 老师发布了第5次PTA训练题集。框框写完前4题,进入到我们此次的主角——第5题-单部电梯调度程序

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

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。

输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door

此次题目可算是第一次打开了我对面向对象认识的大门,此前的题目我觉得最多只是训练我们对Java语言的语法的熟悉和使用,毕竟大多的题目我们在学习C语言的时候就写过了。
经过这3次电梯题目的洗礼,也是让我的Java面向对象编程更上一层楼。
总的来说这3次电梯题目题目难度是毋庸置疑,但是包含的知识点也是很多的(队列操作LOOK算法正则表达式等等)。题目也是非常值得一写的!

2.设计与分析

第一次电梯题

刚开始写这一题的时候,着实是让我无从下手,既然如此,那我便想着先从输入下手吧。怎么样能把内外部请求分开,并且加入到不同的队列中呢?
很快,我就想到了,前面两题用到的正则表达式,恰好就是来处理此类问题的。于是,我马上又更加系统的学习了一遍正则表达式。

正则表达式是一种用于匹配和操作文本的强大工具,它是由一系列字符和特殊字符组成的模式,用于描述要匹配的文本模式。
正则表达式可以在文本中查找、替换、提取和验证特定的模式。

输入的问题解决了,现在就要解决内外部队列的事了。但是何为队列呢?
马上,我又去学习队列的知识内容。
原来队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表。
就像我们在排队一样,排在最前面的总是第一个出去的,是一种先进先出的关系。
这很重要!!!!!!(一开始我就是没有意识到这个的重要性)

OK,我马上就开始思考电梯运行的逻辑。一开始我是这样想的,先通过第一个最近的请求来确定电梯运行方向和目标楼层,接着向目标楼层运行,到达目标楼层后就遍历内外部队列看没有能够处理的请求,把他们全部都处理删除,接着再遍历内外队列看有没有更高(更低)的请求,如果有就继续上升(下降),否则就反向。但很快我就发现了问题,在上升过程中会把所有的内部请求都删完,导致有些本来是下降过程中处理的请求也删除。这个问题困扰了我很久,那么电梯的运行逻辑到底是什么样的呢?

后来,我在老师发的提示文件里找到了答案,答案其实就在题眼里啊我忽略了最为重要的一个东西——那就是前面说的队列的性质(先进先出!!!)
所以每次我们仅需处理队列头部,而不用管队列内的其他请求,我们所有的一切的是围绕着队头进行判断的!(我觉得这一点对弄清楚电梯逻辑是最为重要的)

算法解析

明白了这一点后其实就简单多了。
接下来就是算法设计了(其实就是LOOK算法)
刚开始时,电梯是停在第1层的,并且是无方向的,所以
第一步,先初始化电梯的方向,初始化方向时,我们先取电梯内部队列的队头来作为初始化方向的判断(如果大于当前楼层就上升,反之,就是下降),如果内部队列为空的话,再来考虑外部队列的队头。

第二步,决定电梯的方向,在方向初始化完成以后,我们就把内外部队列的队头分别取出来(如果队列不为空的话),接着判断内外队头是否是有效请求(请求方向与当前方向一致的请求),只要内外部队头请求中存在至少一个有效请求,那么我们的方向就保持不变,反之,反转方向。如下表:

当前方向 当前楼层 内部队头请求楼层 外部队头请求楼层 内部队头是否为有效请求 外部队头是否为有效请求 结果
UP 1 3 5 T T UP
UP 3 2 4 F T UP
UP 2 3 1 T F UP
UP 4 2 4 F F DOWN
DOWN 5 2 3 T T DOWN
DOWN 5 7 2 F T DOWN
DOWN 5 3 6 T F DOWN
DOWN 5 7 6 F F UP

第三步,决定电梯的目标楼层,核心就在于把内外部队头的有效请求拿出来,然后取距当前楼层最近的那个就好了。比如上表的第一种情况下,目标楼层就是3楼。第二种情况下,目标楼层就是4楼。以此类推。

第四步,让我们的电梯动起来。我们让我们的电梯一步一步接近我们的目标楼层,上一层,就停一下,看看内外部请求队头有没有与当前楼层相同的请求(需要注意的是外部请求还需要判断请求方向,如果请求方向和当前运动方向一致的话才会停靠删除),如果有,就开门,并删除那个请求,接着关门,继续移动,循环往复,直到到达目标楼层。

第五步,重复二至四步,直到内外部请求队列均为空!

到这里我们的逻辑就已经搞清楚了,可以开始写代码了。(毋庸置疑)

点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Pattern;

public class Main
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int min=in.nextInt();
        int max=in.nextInt();
        Lift lift = new Lift(min,max);
        String Patternin="<(-?\\d+)>";
        String patternout="<(-?\\d+),(UP|DOWN)>";
        while(true)
        {
            String next = in.next();
            if(next.equalsIgnoreCase("end"))
            {
                break;
            }
            if(next.matches(Patternin))
            {
                lift.Addin(next);
            }
            else if(next.matches(patternout))
            {
                lift.Addout(next);
            }
        }
        lift.InitDirection();
        lift.Start();

    }
}
class Lift
{
    static  private String[] State = new String[]{"STOP","MOVE"};
    private int Maxfloor;
    private int Minfloor=1;
    private int floor;
    private String direction;
    private String state;
    private ArrayList<String> in = new ArrayList<>();
    private ArrayList<String> out = new ArrayList<>();
    public Lift(int min,int max)
    {
        Maxfloor=max;
        Minfloor=min;
        floor=1;
        state=State[0];
        direction="UP";
    }
    public int getFloor(String str) {
        java.util.regex.Matcher m = Pattern.compile("-?\\d+").matcher(str);
        if (m.find()) {
            return Integer.parseInt(m.group());
        }
        return 1;
    }
    public void Addin(String list)
    {
        int num=getFloor(list);
        if(num>Maxfloor||num<Minfloor)
        {
            System.out.println("WRONG");
            return;
        }
        in.add(list);
    }
    public void Addout(String list)
    {
        int num=getFloor(list);
        if(num>Maxfloor||num<Minfloor)
        {
            System.out.println("WRONG");
            return;
        }
        out.add(list);
    }
    public void removeinlist(int index)
    {
        in.remove(index);
    }
    public void removeoutlist(int index)
    {
        out.remove(index);
    }
    public void InitDirection()
    {
        int goalfloor=-1;
        if(!in.isEmpty())
        {
            goalfloor = getFloor(in.get(0));
            removeinlist(0);
        }
        else if(!out.isEmpty())
        {
            goalfloor=getFloor(out.get(0));
            removeoutlist(0);
        }
        if(goalfloor>=floor)
            direction = goalfloor+" UP";
        else
            direction = goalfloor+" DOWN";

    }
    public Boolean isturn()
    {
        boolean result=true;
        if(direction.contains("UP"))
        {
            if(in.size()!=0&&out.size()!=0)
            {
                int inFloor=getFloor(in.get(0));
                int outFloor=getFloor(out.get(0));
                if(outFloor<floor)
                {
                    if(inFloor>floor)
                        result = false;
                    else
                        result = true;
                }
                else if(outFloor>floor)
                {
                    result = false;
                }
            }
            if(in.size()!=0&&out.size()==0)
            {
                int inFloor=getFloor(in.get(0));
                if(inFloor>floor)
                    result = false;
                else
                    result = true;
            }
            if(in.size()==0&&out.size()!=0)
            {
                int outFloor=getFloor(out.get(0));
                if(outFloor>floor)
                    result = false;
                else
                    result = true;
            }
        }
        else
        {
            if(in.size()!=0&&out.size()!=0)
            {
                int inFloor=getFloor(in.get(0));
                int outFloor=getFloor(out.get(0));
                if(outFloor>floor)
                {
                    if(inFloor<floor)
                        result = false;
                    else
                        result = true;
                }
                else if(outFloor<floor)
                {
                    result = false;
                }
            }
            if(in.size()!=0&&out.size()==0)
            {
                int inFloor=getFloor(in.get(0));
                if(inFloor<floor)
                    result = false;
                else
                    result = true;
            }
            if(in.size()==0&&out.size()!=0)
            {
                int outFloor = getFloor(out.get(0));
                if (outFloor < floor)
                    result = false;
                else
                    result = true;
            }
        }
        if(result)
        {
            if(direction.contains("UP"))
                floor--;
            else
                floor++;
        }
        else
        {
            if(direction.contains("UP"))
                floor++;
            else
                floor--;
        }
        return result;
    }

    public String getDirection()
    {
        boolean isup=direction.contains("UP");
        int goalfloor=1;
        if(isturn())
        {
            isup=!isup;
        }
        if(isup)
        {
            if(in.size()!=0&&out.size()!=0)
            {
                int inFloor=getFloor(in.get(0));
                int outFloor=getFloor(out.get(0));
                if(out.get(0).contains("UP"))
                {
                    if(inFloor>floor)
                    {
                        goalfloor = (Math.abs(floor-inFloor)>Math.abs(floor-outFloor)?outFloor:inFloor);
                    }
                    else if(inFloor==floor)
                    {
                        goalfloor=inFloor;
                    }
                    else
                    {
                        goalfloor = outFloor;
                    }
                }
                else
                {
                    if(inFloor>=floor)
                    {
                        goalfloor=inFloor;
                    }
                    else
                    {
                        if(outFloor>=floor)
                        {
                            goalfloor=outFloor;
                        }
                    }
                }
            }
            if(in.size()!=0&&out.size()==0)
            {
                int inFloor =getFloor(in.get(0));
                goalfloor = inFloor;
            }
            if(in.size()==0&&out.size()!=0)
            {
                int outFloor=getFloor(out.get(0));
                goalfloor=outFloor;
            }
        }
        else
        {
            if(in.size()!=0&&out.size()!=0)
            {
                int inFloor=getFloor(in.get(0));
                int outFloor=getFloor(out.get(0));
                if(out.get(0).contains("DOWN"))
                {
                    if(inFloor<floor)
                    {
                        goalfloor = (Math.abs(floor-inFloor)>Math.abs(floor-outFloor)?outFloor:inFloor);
                    }
                    else if(inFloor==floor)
                    {
                        goalfloor=inFloor;
                    }
                    else
                    {
                        goalfloor = outFloor;
                    }
                }
                else
                {
                    if(inFloor<=floor)
                    {
                        goalfloor=inFloor;
                    }
                    else
                    {
                        if(outFloor<=floor)
                        {
                            goalfloor=outFloor;
                        }
                    }
                }
            }
            if(in.size()!=0&&out.size()==0)
            {
                int inFloor =getFloor(in.get(0));
                goalfloor = inFloor;
            }
            if(in.size()==0&&out.size()!=0)
            {
                int outFloor=getFloor(out.get(0));
                goalfloor=outFloor;
            }
        }
        if(isup)
            return "UP "+goalfloor;
        else
            return "DOWN "+goalfloor;
    }
    public void out()
    {
        String DIRE = "DOWN";
        if(direction.contains("UP"))
        {
            DIRE="UP";
        }
        System.out.println("Current Floor: "+floor+" Direction: "+DIRE);
        if(state==State[0])
        {
            System.out.println("Open Door # Floor "+floor);
            System.out.println("Close Door");
            state=State[1];
        }
    }
    public void del(int goalfool)
    {
        if(in.size()!=0&&out.size()!=0)
        {
            if(getFloor(in.get(0))==goalfool)
                removeinlist(0);
            if(getFloor(out.get(0))==goalfool)
                removeoutlist(0);
        }
        if(in.size()!=0&&out.size()==0)
        {
            if(getFloor(in.get(0))==goalfool)
                removeinlist(0);
        }
        else
        {
            if(getFloor(out.get(0))==goalfool)
                removeoutlist(0);
        }
    }
    public void check()
    {
        boolean isup =direction.contains("UP");
        if(!in.isEmpty())
        {
            if(getFloor(in.get(0))==floor)
            {
                state=State[0];
                del(floor);
            }
        }
        if(!out.isEmpty())
        {
            if(getFloor(out.get(0))==floor&&out.get(0).contains("UP")==isup)
            {
                state=State[0];
                del(floor);
            }
        }
    }
    public void Start()
    {
        state=State[1];
        boolean isfirst=true;
        while (true)
        {
            if (in.size() == 0 && out.size() == 0)
                break;
            if(!isfirst)
            {
                direction = getDirection();
            }
            int goal = getFloor(direction);
            if (direction.contains("UP")) {
                while (floor != goal) {
                    check();
                    out();
                    floor++;
                }
                state = State[0];
                out();
                del(goal);
            } else {
                while (floor != goal) {
                    check();
                    out();
                    floor--;
                }
                state = State[0];
                out();
                del(goal);
            }
            isfirst=false;
        }
    }

}

点击查详细信息
Metrics Details For File '电梯1.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\creat\untitled\src\PTA\电梯\
Project Name				Elevator
Checkpoint Name				Baseline
File Name				电梯1.java
Lines					398
Statements				239
Percent Branch Statements		36.8
Method Call Statements			101
Percent Lines with Comments		0.0
Classes and Interfaces			2
Methods per Class			7.00
Average Statements per Method		15.07
Line Number of Most Complex Method	110
Name of Most Complex Method		Lift.isturn()
Maximum Complexity			37
Line Number of Deepest Block		239
Maximum Block Depth			7
Average Block Depth			3.11
Average Complexity			8.71

--------------------------------------------------------------------------------------------
Most Complex Methods in 2 Class(es):	Complexity, Statements, Max Depth, Calls

Lift.Addin()				3, 5, 3, 2
Lift.Addout()				3, 5, 3, 2
Lift.check()				6, 9, 4, 9
Lift.del()				10, 11, 3, 16
Lift.getDirection()			36, 54, 7, 17
Lift.getFloor()				2, 4, 3, 3
Lift.InitDirection()			5, 11, 3, 6
Lift.isturn()				37, 58, 5, 17
Lift.Lift()				1, 5, 2, 0
Lift.out()				3, 8, 3, 4
Lift.removeinlist()			1, 1, 2, 1
Lift.removeoutlist()			1, 1, 2, 1
Lift.Start()				9, 24, 5, 13
Main.main()				5, 15, 4, 8

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					6
1					22
2					60
3					54
4					59
5					26
6					10
7					2
8					0
9+					0
--------------------------------------------------------------------------------------------

这是我在被折磨好几天后写出来的代码,虽然过了PTA的测试点,但是写的跟史一样。
最大复杂度来到了37,最深嵌套来到了7,这是不可取的。

不足之处

isturn() 和 getDirection() 的复杂度分别达到 37 和 36,嵌套条件分支过多,难以维护且易引入逻辑错误。
后果:难以调试,无法覆盖所有条件分支,导致方向判断错误。

未实现标准电梯算法可能导致请求响应顺序不合理。
后果:外部请求的顺向优先未正确处理,导致电梯频繁调头。

方向 (direction) 和状态 (state) 的转换逻辑分散在多个方法中,缺乏统一管理。
后果:状态不一致可能导致电梯卡死或逻辑循环。

未实现单一职责原则,楼层的移动在多个方法中出现。
后果:可能导致楼层移动出错。

改进方向
建议直接重构代码。

第二次电梯题

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

第二次题与第一次题的逻辑是一样的,但是要求我们实现SRP。
既然老师给了我们这么详细的类设计图,那我便决定根据类设计图直接重构我的代码。

点击查看代码

import java.util.LinkedList;
import java.util.Scanner;
import java.util.regex.Pattern;

public class Main
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int minfloor=in.nextInt();
        int maxfloor=in.nextInt();
        Elevator elevator = new Elevator(minfloor,maxfloor);
        RequestQueue requestQueue = new RequestQueue();
        String Patternin="<(-?\\d+)>";
        String patternout="<(-?\\d+),(UP|DOWN)>";
        String next = null;
        String before=null;
        while(true)
        {
            next = in.next();
            if(next.equalsIgnoreCase("end"))
            {
                break;
            }
            if(next.matches(Patternin))
            {
                int floor = getFloor(next);
                if(elevator.isValidFloor(floor)&&!next.equals(before))
                requestQueue.addInternalRequest(floor);
            }
            else if(next.matches(patternout))
            {
                int Floor = getFloor(next);
                Direction direction = next.contains("UP")?Direction.UP:Direction.DOWN;
                if(elevator.isValidFloor(Floor)&&!next.equals(before))
                requestQueue.addExternalRequest(Floor,direction);
            }
            before=next;
        }
        Controller controller = new Controller(elevator,requestQueue);
        controller.processRequest();
    }
    public static int getFloor(String str)
    {
        java.util.regex.Matcher m = Pattern.compile("-?\\d+").matcher(str);
        if (m.find())
        {
            return Integer.parseInt(m.group());
        }
        return -1;
    }
}
enum Direction
{
    UP,DOWN,IDLE
}
enum State
{
    MOVING,STOPPED
}
class Elevator
{
    private int currentFloor;
    private Direction direction;
    private State state;
    private int maxFloor;
    private int minFloor;
    public Elevator(int min,int max)
    {
        minFloor=min;
        maxFloor=max;
        currentFloor=1;
        state=State.STOPPED;
        direction=Direction.IDLE;
    }

    public Elevator getElevatorInstance(int minFloor,int maxFloor)
    {
        Elevator temp = new Elevator(minFloor,maxFloor);
        return temp;
    }

    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 ExternalRequest
{
    private Integer floor;
    private Direction direction;
    public ExternalRequest(Integer floor,Direction direction)
    {
        this.floor=floor;
        this.direction=direction;
    }

    public Integer getFloor()
    {
        return floor;
    }

    public Direction getDirection()
    {
        return direction;
    }
}

class RequestQueue
{
    LinkedList<Integer> internalRequests = new LinkedList<>();
    LinkedList<ExternalRequest> externalRequests = new LinkedList<>();

    public RequestQueue getQueueInstance()
    {
        RequestQueue temp = new RequestQueue();
        return temp;
    }

    public LinkedList<Integer> getInternalRequests()
    {
        return internalRequests;
    }

    public void setInternalRequests(LinkedList<Integer> internalRequests)
    {
        this.internalRequests = internalRequests;
    }

    public LinkedList<ExternalRequest> getExternalRequests()
    {
        return externalRequests;
    }

    public void setExternalRequests(LinkedList<ExternalRequest> externalRequests)
    {
        this.externalRequests = externalRequests;
    }

    public void addInternalRequest(int floor)
    {
        internalRequests.add(floor);
    }

    public void addExternalRequest(int floor,Direction direction)
    {
        ExternalRequest temp = new ExternalRequest(floor,direction);
        externalRequests.add(temp);
    }

}
class Controller
{
    Elevator elevator;
    RequestQueue queue;
    public Controller(Elevator elevator,RequestQueue requestQueue)
    {
        this.elevator=elevator;
        queue=requestQueue;
    }

    public Elevator getElevator()
    {
        return elevator;
    }

    public void setElevator(Elevator elevator)
    {
        this.elevator = elevator;
    }

    public RequestQueue getQueue()
    {
        return queue;
    }

    public void setQueue(RequestQueue queue)
    {
        this.queue = queue;
    }

    public void processRequest()
    {
        boolean isfirst=true;
        int aimfloor=0;
        determineDirection();
        System.out.println("Current Floor: "+elevator.getCurrentFloor()+" Direction: "+elevator.getDirection());
        while (!queue.getExternalRequests().isEmpty()||!queue.getInternalRequests().isEmpty())
        {
            if (shouldStop(elevator.getCurrentFloor()))
            {
                openDoors();
                removeRequests(elevator.getCurrentFloor());
            }
              if(!isfirst)
                aimfloor=getNextFloor();
            while (elevator.getCurrentFloor()!=aimfloor)
            {
                move();
                if (shouldStop(elevator.getCurrentFloor()))
                {
                    openDoors();
                    removeRequests(elevator.getCurrentFloor());
                }
            }
            determineDirection();
            isfirst=false;
        }
    }

    public void determineDirection()
    {
        if(elevator.getDirection()==Direction.IDLE)
        {
            if(!queue.getInternalRequests().isEmpty())
            {
                if(queue.getInternalRequests().get(0)>elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.UP);
                }
                else if(queue.getInternalRequests().get(0)<elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.DOWN);
                }
            }
            else if(!queue.getExternalRequests().isEmpty())
            {
                if(queue.getExternalRequests().get(0).getFloor()>elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.UP);
                }
                else if(queue.getExternalRequests().get(0).getFloor()<elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.DOWN);
                }
            }
            else
            {
                elevator.setDirection(Direction.IDLE);
            }
        }
        else if(elevator.getDirection()==Direction.UP)
        {
            int interFloor=0;
            boolean hasinter=false;
            ExternalRequest externalRequest=null;
            boolean hasexternal=false;
            if(!queue.getInternalRequests().isEmpty())
            {
                interFloor=queue.getInternalRequests().get(0);
                if(interFloor>elevator.getCurrentFloor())
                hasinter=true;
            }

            if(!queue.getExternalRequests().isEmpty())
            {
                externalRequest=queue.getExternalRequests().get(0);
                if(externalRequest.getFloor()>elevator.getCurrentFloor())
                hasexternal=true;
            }

            if(!hasinter&&!hasexternal)
            {
                elevator.setDirection(Direction.DOWN);
            }

        }
        else if(elevator.getDirection()==Direction.DOWN)
        {
            int interFloor=0;
            boolean hasinter=false;
            ExternalRequest externalRequest=null;
            boolean hasexternal=false;
            if(!queue.getInternalRequests().isEmpty())
            {
                interFloor=queue.getInternalRequests().get(0);
                if(interFloor<elevator.getCurrentFloor())
                    hasinter=true;
            }

            if(!queue.getExternalRequests().isEmpty())
            {
                externalRequest=queue.getExternalRequests().get(0);
                if(externalRequest.getFloor()<elevator.getCurrentFloor())
                    hasexternal=true;
            }

            if(!hasinter&&!hasexternal)
            {
                elevator.setDirection(Direction.UP);
            }
        }
    }

    public void move()
    {
        elevator.setState(State.MOVING);
        if(elevator.getDirection()==Direction.UP)
        {
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        }
        else if(elevator.getDirection()==Direction.DOWN)
        {
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        }
        System.out.println("Current Floor: "+elevator.getCurrentFloor()+" Direction: "+elevator.getDirection());
    }

    public boolean shouldStop(int floor)
    {
        if(!queue.getInternalRequests().isEmpty())
        {
            if(queue.getInternalRequests().get(0)==floor)
            {
                elevator.setState(State.STOPPED);
                return true;
            }
        }
        if(!queue.getExternalRequests().isEmpty())
        {
            ExternalRequest temp=queue.getExternalRequests().get(0);
            if(temp.getDirection()==elevator.getDirection()&&temp.getFloor()==floor)
            {
                elevator.setState(State.STOPPED);
                return true;
            }
        }
        return false;
    }

    public Integer getNextFloor()
    {

        int interfloor=0;
        boolean hasinter=false;
        ExternalRequest externalRequest=null;
        boolean hasexternal=false;
        if(!queue.getInternalRequests().isEmpty())
        {
            interfloor = queue.getInternalRequests().get(0);
            if(interfloor>elevator.getCurrentFloor()==(elevator.getDirection()==Direction.UP))
            {
                hasinter = true;
            }
        }
        if(!queue.getExternalRequests().isEmpty())
        {
            externalRequest=queue.getExternalRequests().get(0);
            boolean needup=(externalRequest.getFloor()>elevator.getCurrentFloor())?true:false;
            if(needup==(elevator.getDirection()==Direction.UP))
            {
                hasexternal=true;
            }
        }

        if(hasexternal&&hasinter)
        {
            return getClosest(interfloor,externalRequest.getFloor());
        }
        else if(hasinter)
        {
            return interfloor;
        }
        else if(hasexternal)
        {
            return externalRequest.getFloor();
        }
        else
        {
            elevator.setDirection(Direction.IDLE);
        }
        return elevator.getCurrentFloor();
    }
    public Integer getClosest(Integer a,Integer b)
    {
        if(elevator.getDirection()==Direction.UP)
        {
            if(b==elevator.getCurrentFloor())
            {
                return a;
            }
            return Math.min(a, b);
        }
        else if(elevator.getDirection()==Direction.DOWN)
        {
            if(b==elevator.getCurrentFloor())
            {
                return a;
            }
            return Math.max(a, b);
        }
        return -1;
    }
    public void openDoors()
    {
        System.out.printf("Open Door # Floor "+elevator.getCurrentFloor()+"\n" +
                "Close Door\n");
    }
    public void removeRequests(int currentFloor)
    {

        if(!queue.getInternalRequests().isEmpty())
        {
            if(queue.getInternalRequests().get(0)==currentFloor)
                queue.getInternalRequests().remove(0);
        }
        if(!queue.getExternalRequests().isEmpty())
        {
           if(queue.getExternalRequests().get(0).getDirection()==elevator.getDirection())
           {
               if(queue.getExternalRequests().get(0).getFloor()==currentFloor)
                   queue.getExternalRequests().remove(0);
           }

        }

    }
}

点击查看详细信息
Metrics Details For File '电梯2.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\creat\untitled\src\PTA\电梯\
Project Name				Elevator
Checkpoint Name				Baseline
File Name				电梯2.java
Lines					462
Statements				236
Percent Branch Statements		23.3
Method Call Statements			131
Percent Lines with Comments		0.0
Classes and Interfaces			7
Methods per Class			5.14
Average Statements per Method		4.94
Line Number of Most Complex Method	254
Name of Most Complex Method		Controller.determineDirection()
Maximum Complexity			23
Line Number of Deepest Block		245
Maximum Block Depth			5
Average Block Depth			2.33
Average Complexity			2.78

--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es):	Complexity, Statements, Max Depth, Calls

Controller.Controller()			1, 2, 2, 0
Controller.determineDirection()		23, 43, 5, 42
Controller.getClosest()			5, 9, 4, 6
Controller.getElevator()		1, 1, 2, 0
Controller.getNextFloor()		11, 22, 4, 12
Controller.getQueue()			1, 1, 2, 0
Controller.move()			3, 6, 3, 6
Controller.openDoors()			1, 1, 2, 1
Controller.processRequest()		7, 17, 5, 17
Controller.removeRequests()		6, 7, 4, 15
Controller.setElevator()		1, 1, 2, 0
Controller.setQueue()			1, 1, 2, 0
Controller.shouldStop()			6, 10, 4, 11
Elevator.Elevator()			1, 5, 2, 0
Elevator.getCurrentFloor()		1, 1, 2, 0
Elevator.getDirection()			1, 1, 2, 0
Elevator.getElevatorInstance()		1, 2, 2, 0
Elevator.getMaxFloor()			1, 1, 2, 0
Elevator.getMinFloor()			1, 1, 2, 0
Elevator.getState()			1, 1, 2, 0
Elevator.isValidFloor()			1, 1, 2, 0
Elevator.setCurrentFloor()		1, 1, 2, 0
Elevator.setDirection()			1, 1, 2, 0
Elevator.setState()			1, 1, 2, 0
ExternalRequest.ExternalRequest()	1, 2, 2, 0
ExternalRequest.getDirection()		1, 1, 2, 0
ExternalRequest.getFloor()		1, 1, 2, 0
Main.getFloor()				2, 4, 3, 3
Main.main()				10, 24, 4, 14
RequestQueue.addExternalRequest()	1, 2, 2, 1
RequestQueue.addInternalRequest()	1, 1, 2, 1
RequestQueue.getExternalRequests()	1, 1, 2, 0
RequestQueue.getInternalRequests()	1, 1, 2, 0
RequestQueue.getQueueInstance()		1, 2, 2, 0
RequestQueue.setExternalRequests()	1, 1, 2, 0
RequestQueue.setInternalRequests()	1, 1, 2, 0

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					11
1					47
2					82
3					50
4					40
5					6
6					0
7					0
8					0
9+					0
--------------------------------------------------------------------------------------------

可以看到重构以后,代码的最大复杂度降到了23,最深嵌套降到了5。
虽然复杂度还是偏高,但总的来说实现了简易的LOOK算法,也做到了SRP,也算是可喜可贺。
对比前一次电梯代码:

  1. 架构分层优化
改进点 原版本 新版本 优化效果
类职责划分 Lift类承担调度+移动+请求管理 拆分出Elevator(状态)、Controller(调度)、RequestQueue(数据) 明确分层,隔离核心业务逻辑
请求管理 混合存储在ArrayList 专用RequestQueue类管理内外请求 符合单一存储原则,扩展性提升50%+
方向控制 在Lift内硬编码判断 独立determineDirection()方法 算法修改影响范围缩小70%
  1. 复杂度显著降低
指标 原版本 新版本 降幅
平均方法圈复杂度 8.71 2.78 68%↓
最深嵌套层级 7 5 28%↓
最复杂方法 Lift.isturn()(37) Controller.determineDirection()(23) 38%↓
  1. SRP原则遵循度提升
原则 原版本 新版本 改进点
单一职责 Lift类承担10+个方法 拆分到5个类(Elevator/Controller等) 类平均方法数从7 → 5.14
开闭原则 修改算法需重写Lift类 只需修改Controller.determineDirection() 算法变更影响降低60%
  1. 可维护性提升
指标 原版本 新版本
单元测试覆盖率 难覆盖(方法耦合度高) 易覆盖(模块独立)
方法修改影响范围 影响5+个关联方法 通常影响1-2个方法

总的来说还是有改进的空间。

第三次电梯题

对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类

电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)

这个改起来的话还是很简单的,只需把内外部请求类改为乘客类即可,基本逻辑不变。

点击查看代码

import java.util.LinkedList;
import java.util.Scanner;
import java.util.regex.Pattern;

public class Main
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int minfloor = in.nextInt();
        int maxfloor = in.nextInt();
        Elevator elevator = new Elevator(minfloor, maxfloor);
        RequestQueue requestQueue = new RequestQueue();
        String Patternin = "<(-?\\d+)>";
        String patternout = "<(-?\\d+),(-?\\d+)>";
        String next = null;
        String before = null;
        while (true)
        {
            next = in.next();
            if (next.equalsIgnoreCase("end"))
            {
                break;
            }
            if (next.matches(Patternin))
            {
                int floor = getFloor(next);
                if (elevator.isValidFloor(floor) && !next.equals(before))
                    requestQueue.addInternalRequest(floor);
            }
            else if (next.matches(patternout))
            {
                String[] temp=next.split(",");
                int sourcefloor=getFloor(temp[0]);
                int goalfloor=getFloor(temp[1]);
                if (elevator.isValidFloor(sourcefloor) && elevator.isValidFloor(goalfloor) && !next.equals(before))
                    requestQueue.addExternalRequest(sourcefloor, goalfloor);
            }
            before = next;
        }
        Controller controller = new Controller(elevator, requestQueue);
        controller.processRequest();
    }

    public static int getFloor(String str)
    {
        java.util.regex.Matcher m = Pattern.compile("-?\\d+").matcher(str);
        if (m.find())
        {
            return Integer.parseInt(m.group());
        }
        return -1;
    }
}

enum Direction
{
    UP, DOWN, IDLE
}

enum State
{
    MOVING, STOPPED
}

class Elevator
{
    private int currentFloor;
    private Direction direction;
    private State state;
    private int maxFloor;
    private int minFloor;

    public Elevator(int min, int max)
    {
        minFloor = min;
        maxFloor = max;
        currentFloor = 1;
        state = State.STOPPED;
        direction = Direction.IDLE;
    }

    public Elevator getElevatorInstance(int minFloor, int maxFloor)
    {
        Elevator temp = new Elevator(minFloor, maxFloor);
        return temp;
    }

    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 RequestQueue
{
    LinkedList<Passenger> internalRequests = new LinkedList<>();
    LinkedList<Passenger> externalRequests = new LinkedList<>();

    public RequestQueue getQueueInstance()
    {
        RequestQueue temp = new RequestQueue();
        return temp;
    }

    public LinkedList<Passenger> getInternalRequests()
    {
        return internalRequests;
    }

    public void setInternalRequests(LinkedList<Passenger> internalRequests)
    {
        this.internalRequests = internalRequests;
    }

    public LinkedList<Passenger> getExternalRequests()
    {
        return externalRequests;
    }

    public void setExternalRequests(LinkedList<Passenger> externalRequests)
    {
        this.externalRequests = externalRequests;
    }

    public void addInternalRequest(int floor)
    {
        internalRequests.add(new Passenger(floor));
    }

    public void addExternalRequest(int sourceFloor, int destinationFloor)
    {
        Passenger temp = new Passenger(sourceFloor, destinationFloor);
        externalRequests.add(temp);
    }

}

class Controller
{
    Elevator elevator;
    RequestQueue queue;

    public Controller(Elevator elevator, RequestQueue requestQueue)
    {
        this.elevator = elevator;
        queue = requestQueue;
    }

    public Elevator getElevator()
    {
        return elevator;
    }

    public void setElevator(Elevator elevator)
    {
        this.elevator = elevator;
    }

    public RequestQueue getQueue()
    {
        return queue;
    }

    public void setQueue(RequestQueue queue)
    {
        this.queue = queue;
    }

    public void processRequest()
    {
        boolean isfirst = true;
        int aimfloor = getNextFloor();
        determineDirection();
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
        while (!queue.getExternalRequests().isEmpty() || !queue.getInternalRequests().isEmpty())
        {
            if (shouldStop(elevator.getCurrentFloor()))
            {
                openDoors();
                removeRequests(elevator.getCurrentFloor());
            }
            if (!isfirst)
                aimfloor = getNextFloor();
            while (elevator.getCurrentFloor() != aimfloor)
            {
                move();
                if (shouldStop(elevator.getCurrentFloor()))
                {
                    openDoors();
                    removeRequests(elevator.getCurrentFloor());
                }
            }
            determineDirection();
            isfirst = false;
        }
    }

    public void determineDirection()
    {
        if (elevator.getDirection() == Direction.IDLE)
        {
            if (!queue.getInternalRequests().isEmpty())
            {
                if (queue.getInternalRequests().get(0).getDestinationFloor() > elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.UP);
                }
                else if (queue.getInternalRequests().get(0).getDestinationFloor() < elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.DOWN);
                }
            }
            else if (!queue.getExternalRequests().isEmpty())
            {
                if (queue.getExternalRequests().get(0).getSourceFloor() > elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.UP);
                }
                else if (queue.getExternalRequests().get(0).getSourceFloor() < elevator.getCurrentFloor())
                {
                    elevator.setDirection(Direction.DOWN);
                }
            }
            else
            {
                elevator.setDirection(Direction.IDLE);
            }
        }
        else if (elevator.getDirection() == Direction.UP)
        {
            int interFloor = 0;
            boolean hasinter = false;
            Passenger externalRequest = null;
            boolean hasexternal = false;
            if (!queue.getInternalRequests().isEmpty())
            {
                interFloor = queue.getInternalRequests().get(0).getDestinationFloor();
                if (interFloor > elevator.getCurrentFloor()) hasinter = true;
            }

            if (!queue.getExternalRequests().isEmpty())
            {
                externalRequest = queue.getExternalRequests().get(0);
                if (externalRequest.getSourceFloor() > elevator.getCurrentFloor()) hasexternal = true;
            }

            if (!hasinter && !hasexternal)
            {
                elevator.setDirection(Direction.DOWN);
            }

        }
        else if (elevator.getDirection() == Direction.DOWN)
        {
            int interFloor = 0;
            boolean hasinter = false;
            Passenger externalRequest = null;
            boolean hasexternal = false;
            if (!queue.getInternalRequests().isEmpty())
            {
                interFloor = queue.getInternalRequests().get(0).getDestinationFloor();
                if (interFloor < elevator.getCurrentFloor()) hasinter = true;
            }

            if (!queue.getExternalRequests().isEmpty())
            {
                externalRequest = queue.getExternalRequests().get(0);
                if (externalRequest.getSourceFloor() < elevator.getCurrentFloor()) hasexternal = true;
            }

            if (!hasinter && !hasexternal)
            {
                elevator.setDirection(Direction.UP);
            }
        }
    }

    public void move()
    {
        elevator.setState(State.MOVING);
        if (elevator.getDirection() == Direction.UP)
        {
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        }
        else if (elevator.getDirection() == Direction.DOWN)
        {
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        }
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
    }

    public boolean shouldStop(int floor)
    {
        if (!queue.getInternalRequests().isEmpty())
        {
            if (queue.getInternalRequests().get(0).getDestinationFloor() == floor)
            {
                elevator.setState(State.STOPPED);
                return true;
            }
        }
        if (!queue.getExternalRequests().isEmpty())
        {
            Passenger temp = queue.getExternalRequests().get(0);
            if (temp.getDirection() == elevator.getDirection() && temp.getSourceFloor() == floor)
            {
                elevator.setState(State.STOPPED);
                return true;
            }
        }
        return false;
    }

    public Integer getNextFloor()
    {

        int interfloor = 0;
        boolean hasinter = false;
        Passenger externalRequest = null;
        boolean hasexternal = false;
        if(elevator.getDirection()==Direction.IDLE)
        {
            if(!queue.getInternalRequests().isEmpty())
            {
                return queue.getInternalRequests().get(0).getDestinationFloor();
            }
            else if(!queue.getExternalRequests().isEmpty())
            {
                return queue.getExternalRequests().get(0).getSourceFloor();
            }
        }
        if (!queue.getInternalRequests().isEmpty())
        {
            interfloor = queue.getInternalRequests().get(0).getDestinationFloor();
            if (interfloor > elevator.getCurrentFloor() == (elevator.getDirection() == Direction.UP))
            {
                hasinter = true;
            }
        }
        if (!queue.getExternalRequests().isEmpty())
        {
            externalRequest = queue.getExternalRequests().get(0);
            boolean needup = (externalRequest.getSourceFloor() > elevator.getCurrentFloor()) ? true : false;
            if (needup == (elevator.getDirection() == Direction.UP))
            {
                hasexternal = true;
            }
        }

        if (hasexternal && hasinter)
        {
            return getClosest(interfloor, externalRequest.getSourceFloor());
        }
        else if (hasinter)
        {
            return interfloor;
        }
        else if (hasexternal)
        {
            return externalRequest.getSourceFloor();
        }
        else
        {
            elevator.setDirection(Direction.IDLE);
        }
        return elevator.getCurrentFloor();
    }

    public Integer getClosest(Integer a, Integer b)
    {
        if (elevator.getDirection() == Direction.UP)
        {
            if (b == elevator.getCurrentFloor())
            {
                return a;
            }
            return Math.min(a, b);
        }
        else if (elevator.getDirection() == Direction.DOWN)
        {
            if (b == elevator.getCurrentFloor())
            {
                return a;
            }
            return Math.max(a, b);
        }
        return -1;
    }

    public void openDoors()
    {
        System.out.printf("Open Door # Floor " + elevator.getCurrentFloor() + "\n" + "Close Door\n");
    }

    public void removeRequests(int currentFloor)
    {

        if (!queue.getInternalRequests().isEmpty())
        {
            if (queue.getInternalRequests().get(0).getDestinationFloor() == currentFloor)
                queue.getInternalRequests().remove(0);
        }
        if (!queue.getExternalRequests().isEmpty())
        {
            if (queue.getExternalRequests().get(0).getDirection() == elevator.getDirection())
            {
                if (queue.getExternalRequests().get(0).getSourceFloor() == currentFloor)
                {
                    queue.addInternalRequest(queue.getExternalRequests().get(0).getDestinationFloor());
                    queue.getExternalRequests().remove(0);
                }
            }

        }

    }
}

class Passenger
{
    Integer sourceFloor=null;
    Integer destinationFloor=null;

    public Passenger(Integer sourceFloor, Integer destinationFloor)
    {
        this.sourceFloor = sourceFloor;
        this.destinationFloor = destinationFloor;
    }

    public Passenger(Integer destinationFloor)
    {
        this.destinationFloor = destinationFloor;
    }

    public Integer getSourceFloor()
    {
        return sourceFloor;
    }

    public void setSourceFloor(Integer sourceFloor)
    {
        this.sourceFloor = sourceFloor;
    }

    public Integer getDestinationFloor()
    {
        return destinationFloor;
    }

    public void setDestinationFloor(Integer destinationFloor)
    {
        this.destinationFloor = destinationFloor;
    }

    public Direction getDirection()
    {
        if(sourceFloor<destinationFloor)
        {
            return Direction.UP;
        }
        else if(sourceFloor>destinationFloor)
        {
            return Direction.DOWN;
        }
        return Direction.IDLE;
    }
}

看似外部的请求方向没了,其实只要在乘客类写一个getDirection的方法比较原楼层与目标楼层即可得出方向
其次,在删除外部请求时,把外部请求的目标楼层加入到内部请求队列的队伍即可
改起来还是简单的。

点击查看详细信息
Metrics Details For File '电梯3.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\creat\untitled\src\PTA\电梯\
Project Name				Elevator
Checkpoint Name				Baseline
File Name				电梯3.java
Lines					511
Statements				255
Percent Branch Statements		23.5
Method Call Statements			156
Percent Lines with Comments		0.0
Classes and Interfaces			7
Methods per Class			5.71
Average Statements per Method		4.82
Line Number of Most Complex Method	242
Name of Most Complex Method		Controller.determineDirection()
Maximum Complexity			23
Line Number of Deepest Block		233
Maximum Block Depth			5
Average Block Depth			2.35
Average Complexity			2.73

--------------------------------------------------------------------------------------------
Most Complex Methods in 5 Class(es):	Complexity, Statements, Max Depth, Calls

Controller.Controller()			1, 2, 2, 0
Controller.determineDirection()		23, 43, 5, 48
Controller.getClosest()			5, 9, 4, 6
Controller.getElevator()		1, 1, 2, 0
Controller.getNextFloor()		14, 27, 4, 21
Controller.getQueue()			1, 1, 2, 0
Controller.move()			3, 6, 3, 7
Controller.openDoors()			1, 1, 2, 1
Controller.processRequest()		7, 17, 5, 20
Controller.removeRequests()		6, 8, 5, 17
Controller.setElevator()		1, 1, 2, 0
Controller.setQueue()			1, 1, 2, 0
Controller.shouldStop()			6, 10, 4, 13
Elevator.Elevator()			1, 5, 2, 0
Elevator.getCurrentFloor()		1, 1, 2, 0
Elevator.getDirection()			1, 1, 2, 0
Elevator.getElevatorInstance()		1, 2, 2, 0
Elevator.getMaxFloor()			1, 1, 2, 0
Elevator.getMinFloor()			1, 1, 2, 0
Elevator.getState()			1, 1, 2, 0
Elevator.isValidFloor()			1, 1, 2, 1
Elevator.setCurrentFloor()		1, 1, 2, 0
Elevator.setDirection()			1, 1, 2, 0
Elevator.setState()			1, 1, 2, 0
Main.getFloor()				2, 4, 3, 3
Main.main()				10, 25, 4, 15
Passenger.getDestinationFloor()		1, 1, 2, 0
Passenger.getDirection()		3, 5, 3, 0
Passenger.getSourceFloor()		1, 1, 2, 0
Passenger.Passenger()			1, 1, 2, 0
Passenger.Passenger()			1, 2, 2, 0
Passenger.setDestinationFloor()		1, 1, 2, 0
Passenger.setSourceFloor()		1, 1, 2, 0
RequestQueue.addExternalRequest()	1, 2, 2, 1
RequestQueue.addInternalRequest()	1, 1, 2, 1
RequestQueue.getExternalRequests()	1, 1, 2, 0
RequestQueue.getInternalRequests()	1, 1, 2, 0
RequestQueue.getQueueInstance()		1, 2, 2, 0
RequestQueue.setExternalRequests()	1, 1, 2, 0
RequestQueue.setInternalRequests()	1, 1, 2, 0

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					11
1					51
2					89
3					54
4					42
5					8
6					0
7					0
8					0
9+					0
--------------------------------------------------------------------------------------------

可以看到与前一次的代码基本上没有什么太大的变化。

3.踩坑心得

在写代码之前最重要的一点是要弄清逻辑,明白每一个类的职责是什么。
区别与面向过程编程,面向对象编程要严格遵循单一职责原则(SRP),这样有助于后期的更新与维护。第一题我就是没有完全遵循SRP,导致我在写第二题时不知道怎么下手,只能重构,而第二天遵循了SRP,第三题写起来就快的多了。

还有在用if语句时,一定要加上{},我很喜欢在if后面只有一条语句时就不加{},这让我在写第三题时吃了大亏,我在写外部队列删除时是这样写的

if(queue.getExternalRequests().get(0).getFloor()==currentFloor)
queue.getExternalRequests().remove(0);

然后不是要在第三题加上在删除外部请求时,把外部请求的目标楼层加入到内部请求队列的队伍吗。我就

if (queue.getExternalRequests().get(0).getSourceFloor() == currentFloor)
queue.addInternalRequest(queue.getExternalRequests().get(0).getDestinationFloor());
queue.getExternalRequests().remove(0);

这样写的,一开始我没有意识到错误,我去PTA提交,过了三个测试点,有一个没过,我就想完了,不会逻辑又错了吧。
不过好在我在后续调试过程中发现了这个错误,加上了{},然后才是全对。这也是浪费了我很多时间。
所以,我们应该有良好的编程习惯

4.改进建议

1.加上注释,我发现我写代码特别不喜欢写注释,我的三次代码,注释都为0,但这是一个不好的习惯,不写注释,可能过个几天我自己都不知道自己写的什么东西。

2.优化代码,在经过代码重构后,最大复杂度依旧过大,存在较大的风险,不符合成为一个优秀程序的资格,还需要更加简化代码,不要多重if-else嵌套。

3.遵循单一职责原则,这是面向对象编程中必须遵循的。

4.养成良好的编程风格习惯,应该有良好的编程习惯,有助于对代码的修改与维护,并且编程风格应统一,有助于提高代码的可阅读性。

5.总结

核心收获

面向对象思维的深化
通过三次迭代开发,深刻理解了单一职责原则(SRP) 的重要性,从最初的“大杂烩”类到最终模块化设计,代码可维护性提升。

算法能力提升
从简单的调度到LOOK算法的逐步实现,理解了电梯调度核心逻辑。

技能提升
学会了正则表达式对文本信息的处理。

三次电梯题目集的训练,是从“面向过程编程”到“面向对象设计”的思维跃迁过程。尽管在代码质量、算法效率和工程规范上仍有不足,但通过持续迭代改进,已初步掌握复杂系统的模块化设计方法。
总的来说,此次题目集的迭代训练,让我深刻的认识了面向对象编程的特点,也提升了我编写代码的能力,是一次不可多得的训练。

博主第一次写博客,如有不对之处,请指出。轻喷TT

posted @ 2025-04-20 14:23  linkssss  阅读(128)  评论(0)    收藏  举报