bzzd0704

导航

面向过程-面向对象-面向自己:第一次Blog作业🛫

青山缭绕疑无路,忽见千帆隐映来

面向过程-面向对象-面向自己:第一次Blog作业🛫

 

前言: 初学C语言的那个假期,房间内键盘声碎如雨。我盯着屏幕上闪烁的"include<stdio.h> int main()..."当我们刚刚踏入大学校园,接触到第一门编程语言:面向过程的C语言,而紧随其后的新的编程语言便是:面向对象的Java;

在一系列的对何为"面向对象"的讲解上,似乎我总是有些云里雾里,但是在上周,蓝桥杯交卷铃声响起时,梧桐絮正漫过教学楼的玻璃幕墙,我踩着斑驳的代码符号往学校走,指尖还残留着敲击键盘的震颤,回想起当时马上要肌肉记忆一般的输入那个Scanner sc后,我忍俊不禁的笑了一下,却在短短的几秒后,重新记忆起那个困扰我很久的问题,"究竟什么是面向对象"?

砌下落花风起,罗衣特地春寒,有些清冷的春风呼啸着吹了过来,卷起层层绿色的波浪,沁入心脾,我的纠缠的思维似乎也有些豁然开朗了起来...

虽然个人认为本次电梯的题目对我来说实在是有些难如登天,甚至在看到教学楼的电梯时也忍不住去想这个题目的逻辑🤨,写题目的过程简直令我"痛不欲生",但当我蓦然回首,这个朦胧的问题好像渐渐的褪去了身边的迷雾,那就我们跟随着这次电梯的的迭代作业中,再一次体会"面向对象"的实用与快捷吧🤗

 

         

分析与踩坑心得:

三思而后行,再斯可矣

 

        先来看看我的作业集5源码:

点击我折叠代码^-^
 
import java.util.*;

enum Direction {
    UP, DOWN, STOPPED
}

class Request implements Comparable<Request> {
    int floor;
    Direction dir;

    public Request(int floor, Direction dir) {
        this.floor = floor;
        this.dir = dir;
    }

    @Override
    public int compareTo(Request o) {
        // 上行请求按楼层升序,下行请求按降序
        return (this.dir == Direction.UP) ?
                Integer.compare(this.floor, o.floor) :
                Integer.compare(o.floor, this.floor);
    }
}

class Elevator {
    private final int minFloor, maxFloor;
    private int currentFloor;
    private Direction direction;

    // 队列定义
    private final PriorityQueue<Integer> internalUp = new PriorityQueue<>();      // 内部上行目标
    private final PriorityQueue<Integer> internalDown = new PriorityQueue<>(Comparator.reverseOrder()); // 内部下行目标
    private final PriorityQueue<Request> externalUp = new PriorityQueue<>();      // 外部上行请求
    private final PriorityQueue<Request> externalDown = new PriorityQueue<>(Comparator.reverseOrder()); // 外部下行请求

    public Elevator(int min, int max) {
        this.minFloor = min;
        this.maxFloor = max;
        this.currentFloor = min;
        this.direction = Direction.STOPPED;
    }

    // 添加内部请求(按方向拆分)
    public void addInternal(int floor) {
        if (floor < minFloor || floor > maxFloor) return;
        if (floor > currentFloor) internalUp.add(floor);
        else internalDown.add(floor);
    }

    // 添加外部请求(按方向存储)
    public void addExternal(int floor, Direction dir) {
        if (floor < minFloor || floor > maxFloor) return;
        if (dir == Direction.UP) externalUp.add(new Request(floor, dir));
        else externalDown.add(new Request(floor, dir));
    }

    public void run() {
        while (hasPendingRequests()) {
            adjustDirection();
            moveOneStep();
            checkStop();
        }
    }

    private boolean hasPendingRequests() {
        return !internalUp.isEmpty() || !internalDown.isEmpty() ||
                !externalUp.isEmpty() || !externalDown.isEmpty();
    }

    // 核心方向调整逻辑
    private void adjustDirection() {
        if (direction == Direction.STOPPED) {
            // 初始方向选择:优先处理最近的请求
            if (!externalUp.isEmpty()) {
                direction = (externalUp.peek().floor >= currentFloor) ? Direction.UP : Direction.DOWN;
            } else if (!externalDown.isEmpty()) {
                direction = (externalDown.peek().floor <= currentFloor) ? Direction.DOWN : Direction.UP;
            } else if (!internalUp.isEmpty()) {
                direction = Direction.UP;
            } else {
                direction = Direction.DOWN;
            }
        } else {
            // 运行中方向检测:是否有同方向请求
            boolean hasSameDirRequests = (direction == Direction.UP) ?
                    (!internalUp.isEmpty() || !externalUp.isEmpty()) :
                    (!internalDown.isEmpty() || !externalDown.isEmpty());

            if (!hasSameDirRequests) {
                direction = (direction == Direction.UP) ? Direction.DOWN : Direction.UP;
            }
        }
    }

    // 单步移动逻辑
    private void moveOneStep() {
        if (direction == Direction.UP && currentFloor < maxFloor) {
            currentFloor++;
        } else if (direction == Direction.DOWN && currentFloor > minFloor) {
            currentFloor--;
        }
        System.out.printf("Current Floor: %d Direction: %s\n", currentFloor, direction);
    }

    // 停靠检测与处理
    private void checkStop() {
        boolean shouldStop = false;

        // 处理内部请求
        if (!internalUp.isEmpty() && internalUp.peek() == currentFloor) {
            internalUp.poll();
            shouldStop = true;
        } else if (!internalDown.isEmpty() && internalDown.peek() == currentFloor) {
            internalDown.poll();
            shouldStop = true;
        }

        // 处理外部请求
        if (direction == Direction.UP && !externalUp.isEmpty() && externalUp.peek().floor == currentFloor) {
            externalUp.poll();
            shouldStop = true;
        } else if (direction == Direction.DOWN && !externalDown.isEmpty() && externalDown.peek().floor == currentFloor) {
            externalDown.poll();
            shouldStop = true;
        }

        if (shouldStop) {
            System.out.printf("Open Door # Floor %d\n", currentFloor);
            System.out.println("Close Door");
        }
    }
}

public class aa {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int min = sc.nextInt();
        int max = sc.nextInt();
        sc.nextLine(); // 处理换行

        Elevator elevator = new Elevator(min, max);

        while (sc.hasNextLine()) {
            String line = sc.nextLine().trim();
            if (line.equalsIgnoreCase("end")) break;

            if (line.matches("<\\d+>|<\\d+,\\s*(UP|DOWN)>")) {
                String content = line.substring(1, line.length()-1).replaceAll("\\s", "");
                if (content.contains(",")) {
                    String[] parts = content.split(",");
                    int floor = Integer.parseInt(parts[0]);
                    Direction dir = Direction.valueOf(parts[1]);
                    elevator.addExternal(floor, dir);
                } else {
                    elevator.addInternal(Integer.parseInt(content));
                }
            }
        }

        elevator.run();
        sc.close();
    }
}

(回过头来自己看的都头晕🤨)

来看一下代码的基本数据:

  • 分支语句占比:25.7%
    方法调用语句数:48
    注释行占比:9.8%
    类和接口数:4
    每个类的平均方法数:2.25
    每个方法的平均语句数:7.89
    最复杂方法:aa.main (),复杂度为 6,位于第 132 行
    最大嵌套深度:5,位于第 147 行
    平均嵌套深度:1.64
    平均复杂度:2.25

 

 

在source monitor中的检测数据为:

通过这三张图片与数据,我们可以分析出以下结论:

复杂度特点:

  • 整体复杂度:平均复杂度为 2.25,最大复杂度在aa.main()方法达到 6 。说明代码整体复杂度处于中等水平,不过aa.main()方法相对复杂,可能是因其承担了输入读取、请求处理和电梯启动等多项功能,导致逻辑集中。
    方法复杂度差异:从具体方法看,aa.main()复杂度为 6,语句数 19,方法调用数 17 ;而像Elevator.Elevator()等方法复杂度仅为 1 。这种差异体现了代码中不同方法功能的难易程度不同,复杂方法集中了较多关键逻辑,简单方法多为基础的初始化等操作。
  • 嵌套深度相关:最大嵌套深度为 5,位于aa.main()方法,平均嵌套深度 1.64 。大部分语句集中在嵌套深度 0 - 2 之间,说明代码中存在部分嵌套较深的逻辑,可能在aa.main()方法中条件判断、循环等结构层层嵌套,影响代码可读性和维护性,不过整体嵌套情况不算特别严重。

代码可读性与可维护性特点:

  • 注释情况:注释行占比仅 9.8% ,较低的注释比例意味着代码中对功能、逻辑的解释说明较少,对于其他开发者或一段时间后的自己,理解代码意图和逻辑会存在一定困难,不利于代码的长期维护。
    分支与方法调用:分支语句占比 25.7%,方法调用语句数 48 。一定比例的分支语句表明代码中存在较多条件判断逻辑,增加了代码理解难度;而较多的方法调用说明代码在功能实现上注重方法间的协作,但也可能使程序执行流程变得复杂,需要梳理方法调用关系来理解整体逻辑。


可视化图表反映的特点:

  • 从图中可以直观看到各项指标的相对情况。如% Comments(注释比例)指标明显较低,与前面分析的注释行占比少相呼应;Max Complexity(最大复杂度)和Max Depth(最大深度)等指标也能通过图表快速感知其在整体代码指标中的位置,帮助开发者整体把握代码的特征。该图表展示了不同嵌套深度下的语句分布情况,与提供的数据表格相互印证。可以清晰看到嵌套深度为 1、2 时语句数较多,直观反映出代码中大部分逻辑处于相对较浅的嵌套层次,但也存在少量嵌套深度达到 5 的情况,这部分存在较复杂的逻辑。

 

那么再来仔细分析一下题集5中各个主要内容:

Direction枚举类:
作用:定义了电梯运行的三个方向,即UP(上行)、DOWN(下行)、STOPPED(停止) 。通过枚举类型,让代码更加语义化,在涉及方向判断和处理的地方,直接使用这些清晰的枚举值,避免使用难以理解的数字或字符串等 “魔法值” ,提高了代码的可读性和可维护性。


我的收获:
对于 Java 初学者来说,这是枚举类型的典型应用场景。通过这个例子可以学习到,当某个变量的取值是有限且固定的几个选项时,使用枚举可以使代码更规范、易读。同时,也能了解到枚举在类型安全性上的优势,编译器会检查对枚举值的使用是否正确,减少运行时错误。


Request类:
作用:代表电梯请求,包含楼层信息floor和方向信息dir ,并且实现了Comparable<Request>接口。在compareTo方法中,根据请求的方向(上行按楼层升序,下行按楼层降序)来确定请求的优先级,方便电梯对请求进行排序和处理,合理规划停靠顺序,提升运行效率。


我的收获:这里是接口实现和对象比较逻辑的很好示范。初学者可以学到如何实现Comparable接口来自定义对象之间的比较规则,理解接口在规范类行为方面的作用。同时,也能体会到根据业务需求(如电梯请求的处理逻辑)来设计类的属性和方法的思路,培养面向对象编程中对业务场景的抽象能力。


Elevator类:
属性:通过多个PriorityQueue分别存储内部上行、内部下行、外部上行和外部下行的请求队列。PriorityQueue的使用可以根据楼层和方向自动对请求进行排序,方便管理和处理请求。
方法
addInternal和addExternal方法用于添加内外部请求,通过判断请求楼层是否在有效范围内以及请求方向,将请求合理添加到对应的队列中,保证了请求添加的合法性和有序性。


run方法是电梯运行的核心逻辑,通过循环不断检查是否有未处理的请求,调用adjustDirection调整运行方向、moveOneStep移动电梯以及checkStop检查是否停靠,实现了电梯运行过程的完整模拟。


adjustDirection方法实现了电梯运行方向的动态调整,根据当前电梯状态(停止或运行中)以及各请求队列的情况,决定电梯的运行方向,是电梯智能运行的关键逻辑。


moveOneStep方法实现了电梯的单步移动,根据当前运行方向和楼层边界进行移动,并打印当前楼层和方向信息,简单直观地展示电梯的移动过程。


checkStop方法检查电梯是否应该在当前楼层停靠,通过检查内外部请求队列中是否存在当前楼层的请求,决定是否开门和关门,处理电梯停靠的业务逻辑。

 

 

我的收获:这个类展示了丰富的面向对象编程技巧。从属性的设计上,我学会如何选择合适的数据结构(如PriorityQueue )来存储和管理数据,以满足业务需求。在方法设计方面,每个方法功能单一且职责明确,体现了高内聚的设计原则,这对于我这个初学者理解如何拆分复杂业务逻辑,编写可维护的代码非常有帮助。此外,复杂逻辑的实现(如adjustDirection )也能让我接触到如何分析和解决实际问题,锻炼逻辑思维能力。

那么对于题集五的总结:这里将"封装"属性体现的淋漓尽致:

  • 比如咱先看Elevator类里的属性封装哈。像minFloor 、maxFloor 、currentFloor 、direction这些属性,都被设置成private。这就好比给它们都上了把锁,外面的代码没办法直接跑进去改它们的值。为啥要这样呢?就拿currentFloor来说吧,要是外面的代码能随便改它,那电梯楼层可就乱套了,一会儿上一会儿下的,程序不得出大问题。所以通过把这些属性藏起来,我们只能靠类里面专门的方法,像构造方法或者添加请求的方法,去间接调整它们。这样一来,电梯的状态就能稳稳当当,按我们设定的逻辑来走。
  • 那么对于方法封装:在每个类里头,方法都各司其职。就说Elevator类,addInternal方法就一门心思处理内部请求的添加,别的事儿它不管;adjustDirection方法呢,就专注调整电梯运行方向。这就像给每个方法都安排了明确的任务,代码结构一下子就清爽多了。以后要是想改改添加请求的方式,或者优化下方向调整逻辑,直接找到对应的方法就行,不用在一堆乱七八糟的代码里瞎找,维护起来可方便多了。

 

 

但是,第一次电梯作业并不能很好的体现多类设计,"面向对象"的特征,于是我们来到第二次作业,多类封装:

说实话,第一眼看到这个类之间的关系,简直要了我的小命🐽!但是当我真的静下心来分析,思考后,却发现这个类图反而是极大的帮助我理清了思路,那让我们一起来看看:

还是点我折叠代码^-^
 import java.util.Iterator;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Scanner;

public class bb {
    public enum Direction {
        UP,
        DOWN,
        IDLE
    }

    public enum State {
        MOVING, STOPPED
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int minFloor = scanner.nextInt();
        int maxFloor = scanner.nextInt();
        scanner.nextLine(); // 消耗换行符

        // 初始化电梯系统
        Elevator elevator = new Elevator(minFloor, maxFloor);
        RequestQueue queue = new RequestQueue(elevator);
        Controller controller = new Controller(elevator, queue);

        while (true) {
            String input = scanner.nextLine().trim();
            if (input.equalsIgnoreCase("end")) {
                break;
            }

            try {
                if (input.startsWith("<") && input.endsWith(">")) {
                    String content = input.substring(1, input.length() - 1).trim();
                    if (content.contains(",")) {
                        // 外部请求
                        String[] parts = content.split(",");
                        int floor = Integer.parseInt(parts[0].trim());
                        Direction direction = Direction.valueOf(parts[1].trim().toUpperCase());
                        queue.addExternalRequest(floor, direction);
                    } else {
                        // 内部请求
                        int floor = Integer.parseInt(content);
                        queue.addInternalRequest(floor);
                    }
                }
            } catch (Exception e) {
                System.out.println("Wrong Format");
            }
        }

        controller.processRequests();
    }

    static class ExternalRequest {
        private final Integer floor;
        private final Direction direction;

        public ExternalRequest(Integer floor, Direction direction) {
            this.floor = floor;
            this.direction = direction;
        }

        public Integer getFloor() {
            return this.floor;
        }

        public Direction getDirection() {
            return this.direction;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof ExternalRequest)) return false;
            ExternalRequest that = (ExternalRequest) o;
            return floor.equals(that.floor) && direction == that.direction;
        }

        @Override
        public int hashCode() {
            return Objects.hash(floor, direction);
        }
    }

    static class RequestQueue {
        private final LinkedList<Integer> internalRequests = new LinkedList<>();
        private final LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
        private final Elevator elevator;

        public RequestQueue(Elevator elevator) {
            this.elevator = elevator;
        }

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

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

        public synchronized void addInternalRequest(int floor) {
            if (floor < elevator.minFloor || floor > elevator.maxFloor) {
                return;
            }

            if (!internalRequests.contains(floor)) {
                internalRequests.add(floor);
            }
        }

        public synchronized void addExternalRequest(int floor, Direction direction) {
            if (floor < elevator.minFloor || floor > elevator.maxFloor || direction == Direction.IDLE) {
                return;
            }
            ExternalRequest newReq = new ExternalRequest(floor, direction);
            if (!externalRequests.contains(newReq)) {
                externalRequests.add(newReq);
            }
        }

        public synchronized void removeInternalRequest(int floor) {
            internalRequests.remove(Integer.valueOf(floor));
        }

        public synchronized void removeExternalRequest(int floor, Direction dir) {
            externalRequests.removeIf(req ->
                    req.getFloor() == floor && req.getDirection() == dir);
        }
    }

    static class Elevator {
        private int currentFloor;
        private Direction direction;
        private final int maxFloor;
        private final int minFloor;

        public Elevator(int minFloor, int maxFloor) {
            this.minFloor = minFloor;
            this.maxFloor = maxFloor;
            this.currentFloor = minFloor;
            this.direction = Direction.IDLE;
        }

        public int getCurrentFloor() {
            return currentFloor;
        }

        public Direction getDirection() {
            return direction;
        }

        public void setDirection(Direction direction) {
            this.direction = direction;
        }

        public int getMaxFloor() {
            return maxFloor;
        }

        public int getMinFloor() {
            return minFloor;
        }

        // 新增方法:直接移动到目标楼层(Controller调用)
        public void moveToFloor(int targetFloor) {
            if (!isValidFloor(targetFloor)) return;

            while (currentFloor != targetFloor) {
                if (currentFloor < targetFloor) {
                    moveUp();
                } else {
                    moveDown();
                }
                //System.out.println("Moving to floor: " + currentFloor);
            }
        }

        public void moveUp() {
            if (currentFloor < maxFloor) {
                currentFloor++;
                this.direction = Direction.UP;
            } else {
                this.direction = Direction.DOWN;
            }
            System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
        }

        public void moveDown() {
            if (currentFloor > minFloor) {
                currentFloor--;
                this.direction = Direction.DOWN;
            } else {
                this.direction = Direction.UP;
            }
            System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
        }

        private boolean isValidFloor(int floor) {
            return floor >= minFloor && floor <= maxFloor;
        }
    }

    static class Controller {
        private Elevator elevator;
        private RequestQueue queue;

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

        // 主处理流程
        public void processRequests() {
            // 初始方向确定
            if (elevator.getDirection() == Direction.IDLE) {
                determineDirection();
                if (elevator.getDirection() != Direction.IDLE) {
                    System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
                }
            }

            // 主循环处理所有请求
            while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty()) {
                // 选择下一个要处理的请求
                RequestInfo next = selectNextRequest();

                // 如果没有合适请求,切换方向
                if (next == null) {
                    Direction prevDirection = elevator.getDirection();
                    elevator.setDirection((elevator.getDirection() == Direction.UP) ? Direction.DOWN : Direction.UP);
                    if (prevDirection != elevator.getDirection()) {
                        continue;
                    }
                }

                //判断是否需要改变方向
                Direction targetDirection = (next.floor > elevator.getCurrentFloor()) ? Direction.UP : Direction.DOWN;
                if (targetDirection != elevator.getDirection()) {
                    elevator.setDirection(targetDirection);
                }

                //移动到目标楼层并处理请求
                move(next.floor);
                openDoors();
                removeRequests(next.floor, next.isInternal);

                //检查当前方向是否还有请求
                if (!hasRequestsInCurrentDirection()) {
                    Direction prevDirection = elevator.getDirection();
                    elevator.setDirection((elevator.getDirection() == Direction.UP) ? Direction.DOWN : Direction.UP);
                }
            }
        }

        public Integer processOut() {
            if (queue.getExternalRequests().isEmpty()) {
                return null;
            }
            return queue.getExternalRequests().peek().getFloor();
        }

        public Integer processIn() {
            if (queue.getInternalRequests().isEmpty()) {
                return null;
            }
            return queue.getInternalRequests().peek();
        }
        public boolean getOutDir(){
            int now = elevator.getCurrentFloor();
            int out = queue.getExternalRequests().getFirst().getFloor();
            int in = queue.getInternalRequests().getFirst();
            if(elevator.getDirection().equals(Direction.UP) && now < out){
                if(queue.getExternalRequests().getFirst().getDirection().equals(Direction.UP)){
                    return true;
                }else{
                    return now > in;
                }
            }else if(elevator.getDirection().equals(Direction.DOWN) && now > out){
                if(queue.getExternalRequests().getFirst().getDirection().equals(Direction.DOWN)){
                    return true;
                }else{
                    return now < in;
                }
            }
            return false;
        }
        //用于判断内队列是否同向
        public boolean getInDir(int floor) {
            if(elevator.getCurrentFloor() < floor && elevator.getDirection().equals(Direction.UP)){
                return true;
            }
            else return elevator.getCurrentFloor() > floor && elevator.getDirection().equals(Direction.DOWN);
        }
        public void determineDirection() {
            if (queue.getInternalRequests().isEmpty() && queue.getExternalRequests().isEmpty()) {
                return;
            }

            // 均同向,执行更近的队列请求
            if (getOutDir() && getInDir(queue.getInternalRequests().peek())) {
                elevator.setDirection(queue.getInternalRequests().peek() > elevator.getCurrentFloor() ?
                        Direction.UP : Direction.DOWN);
            }
            // 外同内异,执行同向的外队列请求
            else if (getOutDir()&& !getInDir(queue.getInternalRequests().get(0))) {
                elevator.setDirection(queue.getExternalRequests().peek().getDirection());
            }
            // 内同外异,执行同向的内队列请求
            else if (getInDir(queue.getInternalRequests().peek())&& getInDir(queue.getInternalRequests().get(0))) {
                elevator.setDirection(queue.getInternalRequests().peek() > elevator.getCurrentFloor() ?
                        Direction.UP : Direction.DOWN);
            }
            // 均异向,执行更近的队列请求
            else {
                Integer closest = getClosest(
                        queue.getInternalRequests().peek(),
                        queue.getExternalRequests().peek().getFloor()
                );
                elevator.setDirection(closest > elevator.getCurrentFloor() ? Direction.UP : Direction.DOWN);
            }
        }

        // 移动到目标楼层
        public void move(int targetFloor) {
            elevator.moveToFloor(targetFloor);
        }

        // 获取下一个楼层
        public Integer getNextFloor() {
            RequestInfo next = selectNextRequest();
            return next != null ? next.floor : null;
        }

        // 获取更近的楼层
        public Integer getClosest(Integer a, Integer b) {
            if (a == null) return b;
            if (b == null) return a;
            int distA = Math.abs(a - elevator.getCurrentFloor());
            int distB = Math.abs(b - elevator.getCurrentFloor());
            return distA <= distB ? a : b;
        }

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

        // 我只要删除头队列
        public void removeRequests(int currentFloor, boolean isInternal) {
            if (isInternal) {
                // 只移除匹配的内部请求
                queue.getInternalRequests().remove(Integer.valueOf(currentFloor));
            } else {
                // 只移除匹配的外部请求
                Iterator<ExternalRequest> it = queue.getExternalRequests().iterator();
                while (it.hasNext()) {
                    ExternalRequest req = it.next();
                    // 原逻辑(严格匹配方向)
                    if (req.getFloor() == currentFloor) {
                        it.remove();
                        break;
                    }
                }
            }
        }
        // 检查当前方向是否还有请求
        private boolean hasRequestsInCurrentDirection() {
            Direction currentDirection = elevator.getDirection();
            for (Integer internalFloor : queue.getInternalRequests()) {
                if ((currentDirection == Direction.UP && internalFloor > elevator.getCurrentFloor()) ||
                        (currentDirection == Direction.DOWN && internalFloor < elevator.getCurrentFloor())) {
                    return true;
                }
            }
            for (ExternalRequest externalRequest : queue.getExternalRequests()) {
                if (externalRequest.getDirection() == currentDirection) {
                    return true;
                }
            }
            return false;
        }

        // 请求信息辅助类
        private static class RequestInfo {
            int floor;      // 目标楼层
            boolean isInternal; // 是否为内部请求

            RequestInfo(int floor, boolean isInternal) {
                this.floor = floor;
                this.isInternal = isInternal;
            }
        }

        // 选择下一个要处理的请求
        private RequestInfo selectNextRequest() {
            if (queue.getInternalRequests().isEmpty() && queue.getExternalRequests().isEmpty()) {
                return null;
            }

            // 只有外部请求时返回外部请求
            if (queue.getInternalRequests().isEmpty()) {
                return new RequestInfo(processOut(), false);
            }
            // 只有内部请求时返回内部请求
            if (queue.getExternalRequests().isEmpty()) {
                return new RequestInfo(processIn(), true);
            }

            // 使用新的方向判断逻辑
            boolean internalSameDir = getInDir(queue.getInternalRequests().peek());
            boolean externalSameDir = getOutDir();

            // 两个请求方向都匹配时,选择距离更近的
            if (internalSameDir && externalSameDir) {
                int internalDistance = getDistance(queue.getInternalRequests().peek());
                int externalDistance = getDistance(queue.getExternalRequests().peek().getFloor());
                return internalDistance <= externalDistance ?
                        new RequestInfo(processIn(), true) :
                        new RequestInfo(processOut(), false);
            }
            // 只有内部请求方向匹配
            else if (internalSameDir) {
                return new RequestInfo(processIn(), true);
            }
            // 只有外部请求方向匹配
            else if (externalSameDir) {
                return new RequestInfo(processOut(), false);
            }
            // 都不匹配时选择距离更近的
            else {
                int internalDistance = getDistance(queue.getInternalRequests().peek());
                int externalDistance = getDistance(queue.getExternalRequests().peek().getFloor());
                return internalDistance <= externalDistance ?
                        new RequestInfo(processIn(), true) :
                        new RequestInfo(processOut(), false);
            }
        }
        // 计算距离
        private int getDistance(int floor) {
            return Math.abs(floor - elevator.getCurrentFloor());
        }
    }
}

老样子,先来看看我们的代码基本数据:

 

对比两次表格内容我们可以发现以下神奇的变化🤔:

  • 复杂度方面
    第一次表格:存在复杂度较高的方法,如 Elevator.processRequests() 复杂度达到 32,这表明该方法逻辑非常复杂,可能包含大量的条件判断、循环和递归等操作,阅读性太差了。
    第二次表格:整体复杂度相对降低,没有出现复杂度超过 8 的方法。虽然 bb.main() 复杂度为 8,但相比第一次表格中的高复杂度方法,情况有所改善。这可能意味着代码在设计上进行了优化,将复杂的逻辑进行了拆分,使得每个方法的功能更加单一和清晰。
  • 语句数方面
    第一次表格:Elevator.processRequests() 语句数为 64,说明该方法实现的功能较多,代码量较大。
    第二次表格:各方法语句数普遍较少,大部分在 23 条以下。这可能是因为代码进行了模块化设计,将大功能拆分成多个小方法,每个小方法的代码量减少,更易于维护和测试
  • 最大嵌套深度方面
    第一次表格:Elevator.addRequest() 最大嵌套深度为 5,较深的嵌套会影响代码的可读性和可维护性。
    第二次表格:最大嵌套深度最高为 6(bb.main()),大部分方法嵌套深度在 4 及以下。这可能是在代码优化过程中,对嵌套逻辑进行了梳理,采用了更合理的条件判断和循环结构,减少了不必要的嵌套。
  • 方法调用数方面
    第一次表格:Elevator.processRequests() 方法调用数为 42,表明该方法与其他部分代码的交互非常频繁,耦合度较高。
    第二次表格:方法调用数相对较少,除了 bb.main() 调用数为 17,其他方法调用数多为 0 - 2。这可能意味着代码在设计上更加注重方法的独立性,降低了方法之间的耦合度,提高了代码的灵活性和可扩展性。


那么说人话,当我们对比这两次表格,能清晰地看到代码优化过程中取得的显著进步,而这些进步与面向对象编程的独特特征和优势紧密相连。

  • 第一次表格里,Elevator.processRequests() 方法复杂度高达 32,逻辑复杂得像一团乱麻,这是因为它承担了过多的功能,各个逻辑相互交织,缺乏清晰的边界。这就好比一个大杂烩,各种功能都混在一起,让人难以理解和维护。而在面向对象编程中,封装性是一个重要特征。在第二次表格中,我们能看到复杂度明显降低,没有复杂度超过 8 的方法。这是因为我们运用了第一次电梯中封装的思想,把原本复杂的大逻辑拆分成了一个个小逻辑,每个方法只专注于一项特定的任务。这样一来,无论是编写代码时还是之后回顾代码,都能更加轻松地理解和修改。

 

  • 接着来看最大嵌套深度。第一次表格里,Elevator.addRequest() 最大嵌套深度达到 5,多层嵌套就像一个复杂的迷宫,让代码的可读性和可维护性大打折扣。在面向对象编程中,我们强调代码结构的清晰性和层次性。在第二次表格中,大部分方法的嵌套深度在 4 及以下,虽然 bb.main() 有 6,但整体情况明显改善。这是因为我们在优化代码时,运用面向对象的思想对嵌套逻辑进行了梳理。我们将复杂的嵌套逻辑拆分成多个独立的方法,每个方法负责一个简单的逻辑判断或操作,然后通过调用这些方法来完成整个功能。这样就避免了过多的嵌套,使代码结构更加清晰,就像把一个复杂的树形结构简化成了多个简单的分支,每个分支都一目了然。

 

  • 最后看看方法调用数。第一次表格里,Elevator.processRequests() 调用其他方法 42 次,这表明该方法与其他部分代码的耦合度非常高,就像一张紧密交织的大网,牵一发而动全身。而在面向对象编程中,低耦合性是一个重要的目标。第二次表格里,除了 bb.main() 调用 17 次,其他方法调用数大多在 0 - 2 次。这说明我们在设计代码时,更加注重每个方法的独立性,通过封装和模块化设计,降低了方法之间的耦合度。每个方法就像一个独立的个体,有自己的功能和职责,与其他方法的联系尽可能减少。这样即使某个方法出现问题,也不会对其他方法产生太大的影响,提高了代码的灵活性和可扩展性。


仔细分析一下第二次中各个重要部分的代码:

  • ExternalRequest类
    作用:代表电梯的外部请求,封装了请求楼层floor和请求方向direction两个属性。通过提供getFloor和getDirection方法,对外提供属性访问接口,同时重写了equals和hashCode方法,保证在集合中判断对象相等和哈希存储的正确性。

 

  • RequestQueue类
    属性:使用两个LinkedList分别存储内部请求(internalRequests ,类型为Integer ,表示楼层)和外部请求(externalRequests ,类型为ExternalRequest ) ,并持有Elevator对象的引用,用于判断请求楼层是否在电梯有效楼层范围内。
  • 方法:提供了添加、移除内外部请求的方法,并且使用synchronized关键字进行同步,保证多线程环境下请求队列操作的线程安全性。例如addInternalRequest方法会检查请求楼层的有效性,并在队列中不存在该请求时进行添加。

 

  • Elevator类
    属性:包含当前楼层currentFloor 、运行方向direction 、最大楼层maxFloor 、最小楼层minFloor等属性,记录电梯的运行状态和相关参数。
    方法:提供了获取和设置相关属性的方法,以及电梯移动相关的方法,如moveToFloor可使电梯直接移动到目标楼层,moveUp和moveDown分别实现电梯的上行和下行操作,并在移动时更新方向和打印当前楼层及方向信息。isValidFloor方法用于判断给定楼层是否在电梯有效楼层范围内。

 

  • Controller 类(重头戏)
  • 在电梯控制系统里是核心角色,它负责统筹和处理请求队列中的请求。通过一系列方法,实现了从初始化电梯运行方向,到筛选请求、控制电梯移动、执行开门关门动作以及清理已处理请求等一系列完整的电梯运行控制流程。

先来看个图:                                                         

怎么样,这下是不是非常清晰明了?😄每一个方法打配合,最后大家一起完成这个电梯系统

不过虽然不想承认,但是也就是栽在这里,导致还是没有拿到分....😇,踩坑心得一:

表面上看不出来什么问题对吧?但是在输入

1
20
<3>
<5,DOWN>
<2>
end

得到的结果却...有问题,在电梯到达3楼时,应该判断5>3后,率先考虑方向优先,但是在这却错误的将外部队列的方向植入到电梯里了,所以电梯直接转向了..

后来因为耦合度过高,花了一整天的时间去修改这个问题也只是拆东墙补西墙,无济于事..😭

所以此次教训告诫我,以后写方法时,应该严格分类每一种方法,不然会导致代码的维护很难..

但是这个问题却为第三次的迭代的成功作了铺垫..😉

 

那我们来一起进入最后的篇章:

 

先来看一下新的要求:

 

在有了前两次的逻辑分析,与代码框架的前提下,很顺利的能够分析出这次修改后的逻辑:

举个例子,原来的外部请求时Up和Down也会纳入电梯运行方向的判断,在新的输入中虽然没有方向,但是<3,5>却自带了Up方向,<7,4>自带了Down的方向,所以我们加上:

MoveDirection direction = targetFloor > floor ? MoveDirection.UP : MoveDirection.DOWN;

就可以在外部队列中添加上下属性;在处理上下请求时,加上类似代码即可:

if (elevator.getCurrentFloor() < target) {
    moveElevatorUp(target);
    elevator.setDirection(req.getDirection());
    removeRequests();
} else if (elevator.getCurrentFloor() > target) {
    moveElevatorDown(target);
    elevator.setDirection(req.getDirection());
    removeRequests();
} else {
    openElevatorDoors();
    elevator.setDirection(req.getDirection());
    removeRequests();
}

那我们来分析一下新的代码基础内容:

欸,那此时我们与第二次的代码进行一个对比看一看:

为什么功能增加了,复杂度反而减少了?

来分析以下最后一次的代码内容:

最后的代码喽,辛苦啦^-^
  
import java.util.LinkedList;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Iterator;

public class bala {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int minFloor = scanner.nextInt();
        int maxFloor = scanner.nextInt();
        scanner.nextLine(); // 消耗换行符

        ElevatorCar elevator = new ElevatorCar(1, MoveDirection.UP, minFloor, maxFloor);
        RequestList queue = new RequestList();
        ControlSystem controller = new ControlSystem(elevator, queue);

        while (true) {
            String input = scanner.nextLine().trim();
            if (input.equalsIgnoreCase("end")) {
                break;
            }

            try {
                if (input.startsWith("<") && input.endsWith(">")) {
                    String content = input.substring(1, input.length() - 1).trim();
                    if (content.contains(",")) {
                        // 外部请求
                        String[] parts = content.split(",");
                        int floor = Integer.parseInt(parts[0].trim());
                        int targetFloor = Integer.parseInt(parts[1].trim());
                        MoveDirection direction = targetFloor > floor ? MoveDirection.UP : MoveDirection.DOWN;
                        // MoveDirection direction = MoveDirection.valueOf(parts[1].trim().toUpperCase());
                        if (elevator.checkFloor(floor) && !queue.hasExternal(floor,direction)) {
                            queue.addExternal(floor,targetFloor);
                        }
                    } else {
                        // 内部请求
                        int floor = Integer.parseInt(content);
                        if (elevator.checkFloor(floor) && !queue.hasInternal(floor)) {
                            queue.addInternal(floor);
                        }
                    }
                }
            } catch (Exception e) {
                System.out.println("Wrong Format");
            }
        }

        controller.processRequests();
        scanner.close();
    }
}

class ControlSystem {
    private ElevatorCar elevator;
    private RequestList requests;
    private int outputFlag = 0;

    public ControlSystem(ElevatorCar elevator, RequestList requests) {
        this.elevator = elevator;
        this.requests = requests;
    }

    public void processRequests() {
        while (!requests.getInternals().isEmpty() || !requests.getExternals().isEmpty()) {
            if (requests.getExternals().isEmpty()) {
                handleInternal();
            } else if (requests.getInternals().isEmpty()) {
                handleExternal();
            } else {
                decideProcessingOrder();
            }
        }
    }

    private void decideProcessingOrder() {
        boolean extMatch = checkExternalDirection();
        boolean intMatch = checkInternalDirection();

        if (extMatch && intMatch) {
            processNearest(requests.getInternals().getFirst(), requests.getExternals().getFirst().getFloor());
        } else if (extMatch) {
            handleExternal();
        } else if (intMatch) {
            handleInternal();
        } else {
            processNearest(requests.getInternals().getFirst(), requests.getExternals().getFirst().getFloor());
        }
    }

    private boolean checkExternalDirection() {
        int current = elevator.getCurrentFloor();
        int extFloor = requests.getExternals().getFirst().getFloor();
        int intFloor = requests.getInternals().getFirst();

        if (elevator.getDirection() == MoveDirection.UP && current < extFloor) {
            return requests.getExternals().getFirst().getDirection() == MoveDirection.UP ||
                    (current > intFloor && requests.getExternals().getFirst().getDirection() != MoveDirection.UP);
        } else if (elevator.getDirection() == MoveDirection.DOWN && current > extFloor) {
            return requests.getExternals().getFirst().getDirection() == MoveDirection.DOWN ||
                    (current < intFloor && requests.getExternals().getFirst().getDirection() != MoveDirection.DOWN);
        }
        return false;
    }

    private boolean checkInternalDirection() {
        int current = elevator.getCurrentFloor();
        int target = requests.getInternals().getFirst();
        return (current < target && elevator.getDirection() == MoveDirection.UP) ||
                (current > target && elevator.getDirection() == MoveDirection.DOWN);
    }

    private void processNearest(int internal, int external) {
        int current = elevator.getCurrentFloor();
        if (Math.abs(internal - current) < Math.abs(external - current)) {
            handleInternal();
        } else if (Math.abs(internal - current) > Math.abs(external - current)) {
            handleExternal();
        } else {
            if ((current < internal && current < external) || (current > internal && current > external)) {
                handleBoth();
            } else {
                handleExternal();
            }
        }
    }

    private void handleInternal() {
        int target = requests.getInternals().getFirst();
        if (elevator.getCurrentFloor() < target) {
            elevator.setDirection(MoveDirection.UP);
            moveElevatorUp(target);
        } else if (elevator.getCurrentFloor() > target) {
            elevator.setDirection(MoveDirection.DOWN);
            moveElevatorDown(target);
        }
        if (elevator.getCurrentFloor() == target) {
            openElevatorDoors();
            removeInternal();
        }
    }

    private void handleExternal() {
        ExternalRequest req = requests.getExternals().getFirst();
        if (elevator.getCurrentFloor() < req.getFloor()) {
            elevator.setDirection(MoveDirection.UP);
            moveElevatorUp(req.getFloor());
        } else if (elevator.getCurrentFloor() > req.getFloor()) {
            elevator.setDirection(MoveDirection.DOWN);
            moveElevatorDown(req.getFloor());
        }
        if (elevator.getCurrentFloor() == req.getFloor()) {
            //System.out.println("DEBUG: Adding internal request for floor " + req.getTargetFloor());
            openElevatorDoors();
            elevator.setDirection(req.getDirection());
            if (!requests.hasInternal(req.getTargetFloor())) {
                requests.addInternal(req.getTargetFloor());
            }
            //System.out.println("DEBUG: Internal queue now: " + requests.getInternals());
            removeExternal();
        }
    }

    private void handleBoth() {
        int target = requests.getInternals().getFirst();
        ExternalRequest req = requests.getExternals().getFirst();

        if (elevator.getCurrentFloor() < target) {
            moveElevatorUp(target);
            elevator.setDirection(req.getDirection());
            removeRequests();
        } else if (elevator.getCurrentFloor() > target) {
            moveElevatorDown(target);
            elevator.setDirection(req.getDirection());
            removeRequests();
        } else {
            openElevatorDoors();
            elevator.setDirection(req.getDirection());
            removeRequests();
        }
    }

    private void moveElevatorUp(int target) {
        if (outputFlag != 0) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        }
        while (elevator.getCurrentFloor() < target) {
            System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + MoveDirection.UP);
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        }
    }

    private void moveElevatorDown(int target) {
        if (outputFlag != 0) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        }
        while (elevator.getCurrentFloor() > target) {
            System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + MoveDirection.DOWN);
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        }
        if (elevator.checkFloor(elevator.getCurrentFloor())) {
            Iterator<ExternalRequest> iterator = requests.getExternals().iterator();
            while (iterator.hasNext()) {
                ExternalRequest req = iterator.next();
                if (req.getFloor() == elevator.getCurrentFloor()) {
                    System.out.println("我执行了吗");
                    if (!requests.hasInternal(req.getTargetFloor())) {
                        requests.addInternal(req.getTargetFloor());
                    }
                    iterator.remove();
                }
            }
        }
    }
    private void openElevatorDoors() {
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
        System.out.println("Open Door # Floor " + elevator.getCurrentFloor());
        System.out.println("Close Door");
        outputFlag++;
    }

    private void removeInternal() {
        if (!requests.getInternals().isEmpty()) {
            requests.getInternals().removeFirst();
        }
    }

    private void removeExternal() {
        if (!requests.getExternals().isEmpty()) {
            requests.getExternals().removeFirst();
        }
    }

    private void removeRequests() {
        removeInternal();
        removeExternal();
    }
}

class ElevatorCar {
    private int currentFloor;
    private MoveDirection direction;
    private int minFloor;
    private int maxFloor;
    private ElevatorState state;

    public ElevatorCar(int currentFloor, MoveDirection direction, int minFloor, int maxFloor) {
        this.currentFloor = currentFloor;
        this.direction = direction;
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }

    public int getCurrentFloor() {
        return currentFloor;
    }

    public void setCurrentFloor(int currentFloor) {
        this.currentFloor = currentFloor;
    }

    public MoveDirection getDirection() {
        return direction;
    }

    public void setDirection(MoveDirection direction) {
        this.direction = direction;
    }

    public boolean checkFloor(int floor) {
        return floor >= minFloor && floor <= maxFloor;
    }
}

class RequestList {
    private LinkedList<Integer> internals = new LinkedList<>();
    private LinkedList<ExternalRequest> externals = new LinkedList<>();

    public LinkedList<Integer> getInternals() {
        return internals;
    }

    public LinkedList<ExternalRequest> getExternals() {
        return externals;
    }

    public void addInternal(int floor) {
        internals.addLast(floor);
    }

    public void addExternal(int floor,int target) {
        externals.add(new ExternalRequest(floor, target));
    }

    public boolean hasExternal(int floor, MoveDirection direction) {
        if (externals.isEmpty()) return false;
        ExternalRequest last = externals.getLast();
        return last.getFloor() == floor && last.getDirection() == direction;
    }

    public boolean hasInternal(int floor) {
        try {
            return internals.getLast() == floor;
        } catch (Exception e) {
            return false;
        }
    }
}

class ExternalRequest {
    private int floor;
    private int targetFloor;  // 新增
    private MoveDirection direction;

    public ExternalRequest(int floor, int targetFloor) {
        this.floor = floor;
        this.targetFloor = targetFloor;
        this.direction = targetFloor > floor ? MoveDirection.UP : MoveDirection.DOWN;
    }

    public int getTargetFloor() {
        return targetFloor;
    }

    public int getFloor() {
        return floor;
    }

    public MoveDirection getDirection() {
        return direction;
    }
}

enum MoveDirection {
    UP, DOWN
}

enum ElevatorState {
    STOPPED, MOVING
}

 

第三次电梯代码分析

 

我觉得可以分为以下几个点:

  1. 逻辑拆分:在增加功能的过程中,对原有的复杂代码进行了重构。例如,把一个承担多种功能、逻辑高度耦合的大方法,拆分成了多个功能单一的小方法。就像之前可能 Elevator.processRequests() 方法把电梯运行的各种逻辑都糅合在一起,复杂度很高。但在新代码中,将请求处理逻辑按照不同阶段或类型,分别放到 ControlSystem 类的 handleInternal()、handleExternal() 等方法中,每个方法专注于一件事,使得代码逻辑更加清晰,复杂度自然就降低了。
  2. 算法改进:为实现新功能采用了更高效、简洁的算法。比如在决定电梯请求处理顺序时,新代码可能摒弃了之前复杂的多重嵌套判断,改用更合理的逻辑判断方式。像 ControlSystem.decideProcessingOrder() 方法,通过合理分析内外部请求与电梯当前方向的关系,避免了过多冗余的判断层次,减少了代码的复杂度。
  3. 更好的模块化设计:新代码在增加功能时,更注重模块化。把不同的功能模块划分得更加清晰明确,每个模块(类或方法)的职责单一。比如在电梯控制系统中,ElevatorCar 类专注于电梯状态管理,RequestList 类负责请求队列管理ControlSystem 类承担请求处理和调度。各个模块各司其职,相互之间通过合理的接口进行交互,减少了模块内部的复杂依赖,降低了整体复杂度.
  4. 抽象层次提高:通过引入更抽象的概念和接口,隐藏了底层的复杂实现细节。例如定义了 MoveDirection 枚举来表示电梯运行方向,在代码中使用枚举值来进行方向相关的判断和操作,比直接使用数字或字符串更加直观和简洁,同时也减少了因底层实现带来的复杂度。

 

看着这么多头头是道的分析,是不是以为后面没踩坑了?漏!!!😡

踩坑心得二:

注意:在handleInternal和External中都有:

if (elevator.getCurrentFloor() < target) {
    moveElevatorUp(target);
    elevator.setDirection(req.getDirection());
    removeRequests();
} else if (elevator.getCurrentFloor() > target) {
    moveElevatorDown(target);
    elevator.setDirection(req.getDirection());
    removeRequests();
} else {
    openElevatorDoors();
    elevator.setDirection(req.getDirection());
    removeRequests();
}
 
而在我原来的代码中,两个move过程中会开门,故在测试时,会在最后出现错误:(当我满心欢喜的点击提交答案结果还是四个绿色的大字"答案错误"🤡)
 
当我的外部请求目标楼层与内部请求楼层此刻相同时,我就会在该楼层进行重复的开门关门操作;
private void moveElevatorUp(int target) {
    if (outputFlag != 0) {
        elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
    }
    while (elevator.getCurrentFloor() < target) {
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + MoveDirection.UP);
        elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
    }
}

private void moveElevatorDown(int target) {
    if (outputFlag != 0) {
        elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
    }
    while (elevator.getCurrentFloor() > target) {
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + MoveDirection.DOWN);
        elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
    }
    if (elevator.checkFloor(elevator.getCurrentFloor())) {
        Iterator<ExternalRequest> iterator = requests.getExternals().iterator();
        while (iterator.hasNext()) {
            ExternalRequest req = iterator.next();
            if (req.getFloor() == elevator.getCurrentFloor()) {
                System.out.println("我执行了吗");
                if (!requests.hasInternal(req.getTargetFloor())) {
                    requests.addInternal(req.getTargetFloor());
                }
                iterator.remove();
            }
        }
    }
}

所以,为了修改这个地方,便在几处需要调用openDoor的地方加上严格的条件限制:比如

if (elevator.getCurrentFloor() == req.getFloor()) {
    //System.out.println("DEBUG: Adding internal request for floor " + req.getTargetFloor());
    openElevatorDoors();
    elevator.setDirection(req.getDirection());
    if (!requests.hasInternal(req.getTargetFloor())) {
        requests.addInternal(req.getTargetFloor());
    }
    //System.out.println("DEBUG: Internal queue now: " + requests.getInternals());
    removeExternal();
}

修改之后,我们便能成功的进行判断(两个打印就是我的偷懒的调试嘻嘻)啦!😁

 

改进方法:

删繁就简三秋树,标新立异二月花

  • 降低代码复杂度
    在 代码中,部分方法如 ControlSystem.decideProcessingOrder() 存在逻辑嵌套和复杂判断。我们可以进一步将相关逻辑模块化,例如将方向匹配的判断逻辑拆分到独立的小方法中,以提高代码可读性。同时,通过抽象通用接口或父类,隐藏具体实现细节,降低代码耦合度和复杂度,使代码更易于理解和维护。
  • 增强调度算法的智能性
    当前电梯调度逻辑主要基于简单的方向和距离判断。毕竟对于电梯来说,这是一个现实的问题,我们可以考虑引入更智能的调度策略,例如基于机器学习的动态调度算法。通过分析不同时间段、楼层人流量等因素,动态调整电梯运行策略,以适应多样化的场景,提升电梯运行效率和用户体验。

 

  • 那么对于以后我的启示,我应该更加注重:提高代码的可测试性
    目前代码中部分方法逻辑相互依赖,不利于测试。在正式测试中需要重新设计 ControlSystem 等类的接口和结构,使其更具独立性和可测试性。不再出现第二次电梯中修改代码一整天,最后落得竹篮打水一场空的结局...
  • 遵循单一职责原则并增加能让人看懂的注释
    代码中部分类和方法承担了过多职责,例如 ControlSystem 类同时处理请求调度、电梯移动和开关门等操作。我们应严格遵循单一职责原则,将不同功能拆分到独立的类或方法中。此外,代码中注释较少,对于复杂逻辑(如请求处理顺序的判断)缺乏说明。我们需要在关键代码段添加注释,提升代码的可读性和可维护性,不然能看懂代码的,只有当时的自己和上帝了!

 

总结:

试玉要烧三日满,辨材须待七年期

在撰写这份Blog的过程中,回顾代码编写之路,满是感慨。在这里,虽然我知道不会有什么人在意,我却要衷心的感谢我的同学,有半夜还在为我指导电梯逻辑的班长,有即使身担重任却细心帮我排查问题的潘哥,与我分享经验与调度逻辑的付宇川和王佳欣...我想,要是没有同学们的帮助,我也许会走的更加艰难,初涉编程,面对复杂的逻辑和密密麻麻的代码行,那种痛苦如同置身于黑暗迷宫,四处碰壁却找不到出口。每一次逻辑的错误、每一个难以排查的Bug,都像沉重的石头压在心头,无数次在深夜对着屏幕上的代码,满心怀疑自己是否选错了方向。

“路漫漫其修远兮,吾将上下而求索”,这句诗恰如其分地描绘了那段艰难时光。但我未曾放弃,在不断的摸索、查阅资料、请教他人中,一点点剖析问题,逐步优化代码。当终于让电梯按照预期的规则流畅运行,那种柳暗花明的得意难以言表,仿佛在黑暗中看到了黎明的曙光,满心都是成就感。

希望老师们能在今后的课程上带我们讲解一些具有针对性的题目,并且复盘一些pta里的题目,当然,我也会加倍努力,为今后的学习道路作好铺垫🏃‍♀️

这次经历于我而言,是一次宝贵的成长。它让我明白,面对复杂的编程任务,不能被困难吓倒,要像拆解复杂问题一样,将大目标细化为一个个可解决的小问题,逐个击破。在未来的编程道路上,我会带着这份坚持与智慧继续前行,勇敢面对新的挑战,不断提升自己,在代码的世界中创造更多可能 !

posted on 2025-04-20 14:10  狛枝z  阅读(52)  评论(0)    收藏  举报