difeny

 

第一次blog作业

一.前言

最初着手开发电梯调度程序时,我充满了信心,觉得只要实现基本的楼层请求处理和电梯运行模拟就大功告成。于是,我快速搭建起了基础框架:用 Request 类记录每一个电梯请求的楼层与方向;封装了一个简易的 RequestQueue 类来管理请求队列;Elevator 类则承担起电梯运行的核心逻辑。然而,当我真正开始编写电梯调度核心方法,比如 getNextRequest 和 moveToFloor 时,才发现事情远没有想象中简单。复杂的逻辑判断和嵌套循环让代码变得异常臃肿,可读性几乎为零。那一刻,我深刻体会到,编程不能只追求功能的实现,代码的质量和可维护性同样至关重要。在一次又一次的修改,优化后我才得到了最终的答案。

二.设计过程

以第6次作业为例

点击查看代码
import java.util.*;
class Request {
    int floor;
    String direction;
    public Request(int floor, String direction) {
        this.floor = floor;
        this.direction = direction;
    }
}
class queue{
    Queue<Request> q=new LinkedList<Request>();
    void add(Request r){
        q.add(r);
    }
    Request peek(){
        return q.peek();
    }
    Request poll(){
        return q.poll();
    }
    boolean isEmpty(){
        return q.isEmpty();
    }
}
class Control{
    Elevator elevator;
    int minFloor;
    int maxFloor;
    public Control(Elevator elevator, int minFloor, int maxFloor) {
        this.elevator = elevator;
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }
    void add(String s)
    {
        if (s.contains(",")) {
            String[] parts = s.split(",");
            int floor = Integer.parseInt(parts[0]);
            String direction = parts[1];
            if(floor<=maxFloor&&floor>=minFloor)
            elevator.getoq().add(new Request(floor, direction));
        } else {
            int floor = Integer.parseInt(s);
            if(floor<=maxFloor&&floor>=minFloor)
            elevator.getiq().add(new Request(floor, null));
        }
    }
}
class Elevator {
    private int currentFloor = 1;
    private String status = "Stopped";
    private String direction = "UP";
    queue iq=new queue();
    queue oq=new queue();
    void setfloor(int floor)
    {
        this.currentFloor=floor;
    }
    queue getiq()
    {
        return iq;
    }
    queue getoq()
    {
        return oq;
    }
    public void run() {
        System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
        while (!iq.isEmpty() || !oq.isEmpty()) {
            Request nextRequest = getNextRequest();
            if (nextRequest == null) {
                break;
            }
            moveToFloor(nextRequest);
        }
    }
    private Request getNextRequest() {
        Request internal = iq.peek();
        Request external = oq.peek();

        if (internal == null && external == null) {
            return null;
        }

        if(direction.equals("UP"))
        {
            if(internal == null)
            {
                if(external.floor > currentFloor)
                {
                    return external;
                }
                else
                {
                    direction = "DOWN";
                    return external;
                }
            }

            if(external == null)
            {
                if(internal.floor > currentFloor)
                {
                    return internal;
                }
                else
                {
                    direction = "DOWN";
                    return internal;
                }
            }
            if(internal.floor>currentFloor||external.floor>currentFloor&&external.direction.equals("UP"))
            {
                if(external.direction.equals("DOWN")||external.floor<currentFloor)return internal;

                if(internal.floor<currentFloor)return external;

                if (Math.abs(internal.floor - currentFloor) < Math.abs(external.floor - currentFloor)) {
                    return internal;
                } else {
                    return external;
                }
            }
            else
            {
                direction ="DOWN";

                if(external.direction.equals("DOWN")&&external.floor>currentFloor)
                {
                    direction="UP";
                    return external;
                }
   if(external.direction.equals("UP"))
        {
        return internal;
   }
                if (Math.abs(internal.floor - currentFloor) < Math.abs(external.floor - currentFloor)) {
                    return internal;
                } else {
                    return external;
                }
            }
        }
        if(direction.equals("DOWN"))
        {
            if(external==null) {
                if (internal.floor > currentFloor) {
                    direction = "UP";
                    return internal;
                } else {
                    return internal;
                }
            }
            if(internal==null) {
                if (external.floor > currentFloor) {
                    direction = "UP";
                    return external;
                } else {
                    return external;
                }
            }
            if(internal.floor<currentFloor||external.floor<currentFloor&&external.direction.equals("DOWN"))
            {
                if(external.direction.equals("UP"))return internal;
                if(internal.floor>currentFloor)return external;
                if (Math.abs(internal.floor - currentFloor) < Math.abs(external.floor - currentFloor)) {
                    return internal;
                } else {
                    return external;
                }
            }
            else
            {
                direction ="UP";
                if(external.direction.equals("UP")&&external.floor<currentFloor)
                {
                    direction="DOWN";
                    return external;
                }
                if (Math.abs(internal.floor - currentFloor) < Math.abs(external.floor - currentFloor)) {
                    return internal;
                }
                else
                {
                    return external;
                }
            }
        }
        return null;
    }
    private void moveToFloor(Request request) {
        int nowFloor =currentFloor;
        boolean flag=false;
        if(direction.equals("UP"))
        {
            while (request.floor > currentFloor) {
                flag=true;
                if(currentFloor != nowFloor)
                    System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
                currentFloor++;

            }
            if(flag==true)
            System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
            System.out.println("Open Door # Floor " + currentFloor);
            System.out.println("Close Door");
            while (!iq.isEmpty() && iq.peek().floor == request.floor) {
                iq.poll();
            }
            
            while(!oq.isEmpty() && oq.peek().floor == request.floor&&oq.peek().direction==request.direction) {

        
                oq.poll();
            }
            if(request.direction!=null&&request.direction.equals("DOWN"))direction="DOWN";
        }
        else
        {
            boolean flag1=false;
            while (request.floor < currentFloor) {
                flag1=true;
                if(currentFloor != nowFloor)
                    System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
                currentFloor--;
            }
            if(flag1==true)
            System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
            System.out.println("Open Door # Floor " + currentFloor);
            System.out.println("Close Door");
            while (!iq.isEmpty() && iq.peek().floor == request.floor) {
            
                iq.poll();
            }
            while(!oq.isEmpty() && oq.peek().floor == request.floor&&oq.peek().direction==request.direction) {
            
                oq.poll();
            }
            if(request.direction!=null&&request.direction.equals("UP"))direction="UP";
        }
    }
}
public class Main{
    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();
        elevator.setfloor(minFloor);
        Control control = new Control(elevator, minFloor, maxFloor);
        String input,next="";
        while (!(input = scanner.nextLine()).equalsIgnoreCase("end")) {
            if(input.equals(next))continue;
            next=input;
            input = input.replace("<", "").replace(">", "");
            control.add(input);
        }
        elevator.run();
    }
}

类的设计分析

类图

1. Request 类

功能:该类用于表示一个电梯请求,包含请求的楼层 floor 以及请求的方向 direction。
优点:将请求的相关信息封装在一起,提升了代码的可读性与可维护性,使其他类能方便地处理请求对象。
不足:缺乏对输入参数的验证,例如 direction 可能输入无效值。

2. queue 类

功能:对 Queue 进行了简单封装,提供了添加请求、查看队首请求、移除队首请求以及判断队列是否为空的方法。
优点:封装了队列操作,让其他类能更便捷地使用队列,降低了代码的耦合度。
不足:类名 queue 不符合 Java 的命名规范,应使用大写字母开头的驼峰命名法,如 RequestQueue。

3. Control 类

功能:该类负责接收用户输入的请求,并依据输入格式将请求添加到电梯的内部队列或外部队列。
优点:将请求的处理逻辑集中在一个类中,增强了代码的可维护性。
不足:add 方法的逻辑较为复杂,包含了较多的条件判断,可考虑将部分逻辑提取成独立的方法以提高代码的可读性。

4. Elevator 类

功能:该类是核心类,模拟电梯的运行。包含电梯的当前楼层、状态、方向,以及内部请求队列和外部请求队列。提供了运行电梯、获取下一个请求和移动到指定楼层的方法。
优点:
封装了电梯的各种属性和行为,使代码结构清晰。
getNextRequest 方法根据电梯的当前方向和请求情况,选择合适的下一个请求,逻辑相对完整。
不足:
getNextRequest 方法和 moveToFloor 方法的逻辑非常复杂,包含大量的条件判断和嵌套,代码的可读性和可维护性较差。
部分代码存在重复,如在 moveToFloor 方法中,处理电梯上升和下降的逻辑有很多相似之处,可以考虑提取公共部分。

5. Main 类

功能:该类是程序的入口点,负责读取用户输入,创建电梯和控制器对象,并启动电梯运行。
优点:将程序的启动逻辑集中在一个类中,使代码结构清晰。
不足:输入处理部分的代码较为繁琐,例如使用 scanner.nextLine() 和 scanner.nextInt() 混合读取输入,容易引发输入异常

sourcemonitor解析代码

其中sourcemonitor图中解释如下:

行数:261 行
语句数:177 条
分支语句百分比:31.6% ,意味着约四分之一语句是分支逻辑(if-else)
方法调用语句数:70 条
注释行百分比:0.0% ,即代码无注释
类和接口数量:5 个
每个类的平均方法数:2.80 个
每个方法的平均语句数):10.43条
最复杂方法的行号:77 行,方法为 Elevator.getNextTargetFloor()
最大复杂度为43,方法也是Elevator.getNextTargetFloor()
最深代码块行号:91 行
最大代码块深度为5
平均代码块深度:2.93
平均复杂度:6.21

3.踩坑心得

思考代码逻辑时不严谨,导致最后写完的代码不能完全正确,并且想要修改也异常困难,我开始逐行的去查找错误最后并未发现问题,反而染费了大量的时间,最后重新写一遍才写对。
字母大小写要明确,不然最后的bug会有很多,写完IDEA报错几十个点会吓到人的
在处理请求队列时,没有及时移除已处理的请求,导致电梯在同一楼层反复开门关门。例如,moveToFloor方法中,没有从iq或oq队列中删除已到达楼层的请求,导致代码最开始一直死循环
解决方法:在请求处理完成后,使用poll()方法从队列中移除已处理的请求。

4.改进建议

设计逻辑严谨,排版代码的类有序且美观,使代码的可读性更上一层楼
题目并不难,但要做到完美确很难,在写题目的过程中发展自己的多方面
如代码的面向对象性,可读性,然后做到代码少bug。

5.总结

经过这几次的电梯调度程序,使我加深了对java的理解,并初次体验了java的风格和魅力,虽然过程中遇到的新难题也很多,但也一一解决了
但java学习才刚刚开始,应该不骄不躁继续努力
总的的来说题目很好,过程也很好

posted on 2025-04-20 20:18  difeny  阅读(19)  评论(0)    收藏  举报

导航