设计电梯系统

2022-04-30  本文已影响0人  放开那个BUG

1、前言

电梯系统可以只采用一个队列,然后可以决定请求的方向:

  • 如果无请求,则根据请求的楼层与当前楼层相比,决定是 UP 还是 Down
  • 如果电梯方向为 UP,且当前楼层之上无请求,则根据请求的楼层与当前楼层相比,决定是 UP 还是 Down
  • 如果电梯方向为 Down,且当前楼层之下无请求,则根据请求的楼层与当前楼层相比,决定是 UP 还是 Down

电梯系统应该也算是一个管理类系统,不管是管理类还是预定类、实物类,都是非常经典的主体、input、output 形式。

那么主体肯定是一个电梯系统,input 是用户输入的 Request,output 是电梯(控制哪个电梯服务,为了简单这里使用一部电梯)。而且我们只考虑人在电梯里按按钮的情况,不考虑外部按按钮的情况。

2、设计

那么很清楚的能想到有这几个类:Request、EvelatorSystem、Evelator、Status

Request 有 level 属性,表示要去的楼层。

Status 是个枚举,标识电梯的方向,是 Up、Down 还是 Idle。

EvelatorSystem 主要持有 Evelator 的引用,它处理请求相当于 Evelator 处理请求。

Evelator 是整个电梯系统的核心类,主要有以下几个属性和方法:


Evelator 类图

属性:

  • upStops:向上需要去的楼层
  • downStops:向下需要去的楼层
  • currentLevel:电梯现在所在的楼层
  • status:电梯现在的方向

方法:

  • handlerInternalRequest(Request request):根据现在的方向来决定是向下还是向上
  • openGate():在第几层开门
  • closeGate():在第几层关门,需要清理一下状态
  • noneRequests(boolean[] stops):是否无任何请求

首先,我们假设先摁了 3、6层,到达3层后又摁了2层,如果把2放到一个队列里,那么不管取最大还是最小都不行。所以分为了两个队列,分布放向上或者向下要去的楼层。当然是根据条件判断的。

3、代码

ElevatorSystem:

/**
 * @author xushu
 * @create 4/30/22 5:39 PM
 * @desc 不要引入外部按上下按钮,会使你的系统变得复杂。只考虑人在电梯按按钮
 */
public class ElevatorSystem {

    private Elevator elevator;

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

    public void handlerRequest(Request request) throws Exception {
        this.elevator.handlerInternalRequest(request);
    }

    public void processRequests() throws Exception {
        this.elevator.handlerInternalRequest(new Request(8));
        this.elevator.handlerInternalRequest(new Request(3));
        this.elevator.handlerInternalRequest(new Request(11));
        Random random = new Random();
        while (true){
            if(elevator.isSomeThingLeftInStops()){
                elevator.openGate();
                elevator.closeGate();

                this.elevator.handlerInternalRequest(new Request(random.nextInt(12) + 1));
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ElevatorSystem elevatorSystem = new ElevatorSystem(new Elevator(12));

        elevatorSystem.processRequests();
    }
}

Request:

public class Request {

    protected int level;

    public Request(int level) {
        this.level = level;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }
}

Status:

/**
 * @author xushu
 * @create 4/30/22 6:01 PM
 * @desc 电梯的方向
 */
public enum  Status {
    UP,
    DOWN,
    IDLE
}

Elevator(两个队列的):

public class Elevator {

    /**
     * 向上需要去的楼层
     */
    private boolean[] upStops;

    /**
     * 向下需要去的楼层
     */
    private boolean[] downStops;

    /**
     * 电梯现在所在的楼层
     */
    private int currentLevel;

    /**
     * 电梯现在的方向
     */
    private Status status;

    public Elevator(int n) {
        this.upStops = new boolean[n];
        this.downStops = new boolean[n];
        this.currentLevel = 0;
        this.status = Status.IDLE;
    }

    public void handlerInternalRequest(Request request) throws Exception {
        if(request.level <= 0 || request.level > upStops.length){
            throw new Exception("楼层不合法");
        }

        // 无论电梯向上还是向下运行,只要你的楼层比当前楼层大,那就放入 up 队列,否则放入 down 队列
        if(request.level - (currentLevel + 1) <= 0){
            downStops[request.level - 1] = true;
            if(noneRequests(upStops)){
                status = Status.DOWN;
            }
        }else {
            upStops[request.level - 1] = true;
            if(noneRequests(downStops)){
                status = Status.UP;
            }
        }
    }

    public void openGate(){
        switch (status){
            case UP:
                for (int i = currentLevel; i < upStops.length; i++) {
                    if(upStops[i]) {
                        upStops[i]  = false;
                        currentLevel = i;
                        break;
                    }
                }
                break;
            case DOWN:
                for(int i = currentLevel; i >= 0; i--) {
                    if(downStops[i]) {
                        downStops[i] = false;
                        currentLevel = i;
                        break;
                    }
                }
                break;
        }
        System.out.println("方向是:" + status.name() + ", 楼层是:" + (currentLevel + 1) +  "开门!");
    }

    public void closeGate(){
        System.out.println("方向是:" + status.name() + ", 楼层是:" + (currentLevel + 1) + "关门!");

        if(noneRequests(upStops) && noneRequests(downStops)){
            status = Status.IDLE;
        }else if(noneRequests(upStops) && !noneRequests(downStops)){
            status = Status.DOWN;
        }else {
            status = Status.UP;
        }
    }

    public boolean noneRequests(boolean[] stops){
        for (int i = 0; i < stops.length; i++) {
            if(stops[i]){
                return false;
            }
        }
        return true;
    }

    public boolean isSomeThingLeftInStops(){
        for (int i = 0; i < upStops.length; i++) {
            if(upStops[i] || downStops[i]){
                return true;
            }
        }
        return false;
    }
}

Elevator(一个队列的):

public class Elevator {

    /**
     * 要停的楼层
     */
    private boolean[] stops;

    /**
     * 电梯现在所在的楼层
     */
    private int currentLevel;

    /**
     * 电梯现在的方向
     */
    private Status status;

    public Elevator(int n) {
        this.stops = new boolean[n];
        this.currentLevel = 0;
        this.status = Status.IDLE;
    }

    public void handlerInternalRequest(Request request) throws Exception {
        if(request.level <= 0 || request.level > stops.length){
            throw new Exception("楼层不合法");
        }

        // 如果无请求,只要你的楼层比当前楼层大,电梯方向向上;否则向下
        // 如果电梯方向向上,且向上无请求,则根据请求决定电梯方向
        // 如果电梯方向向下,且向下无请求,则根据请求决定电梯方向
        if(noneRequests(stops) || (status.equals(Status.UP) && noUpRequests(stops)) || (status.equals(Status.DOWN) && noDownRequests(stops))){
            status = request.level - (currentLevel + 1) <= 0 ? Status.DOWN : Status.UP;
        }
        stops[request.level - 1] = true;
    }

    public void openGate(){
        switch (status){
            case UP:
                for (int i = currentLevel; i < stops.length; i++) {
                    if(stops[i]) {
                        stops[i]  = false;
                        currentLevel = i;
                        break;
                    }
                }
                break;
            case DOWN:
                for(int i = currentLevel; i >= 0; i--) {
                    if(stops[i]) {
                        stops[i] = false;
                        currentLevel = i;
                        break;
                    }
                }
                break;
        }
        System.out.println("方向是:" + status.name() + ", 楼层是:" + (currentLevel + 1) +  "开门!");
    }

    public void closeGate(){
        System.out.println("方向是:" + status.name() + ", 楼层是:" + (currentLevel + 1) + "关门!");

        if(noneRequests(stops)){
            status = Status.IDLE;
        }
    }

    public boolean noneRequests(boolean[] stops){
        for (int i = 0; i < stops.length; i++) {
            if(stops[i]){
                return false;
            }
        }
        return true;
    }

    public boolean noUpRequests(boolean[] stops){
        for (int i = currentLevel; i < stops.length; i++) {
            if(stops[i]){
                return false;
            }
        }
        return true;
    }

    public boolean noDownRequests(boolean[] stops){
        for (int i = currentLevel; i >= 0; i--) {
            if(stops[i]){
                return false;
            }
        }
        return true;
    }

    public boolean isSomeThingLeftInStops(){
        for (int i = 0; i < stops.length; i++) {
            if(stops[i] || stops[i]){
                return true;
            }
        }
        return false;
    }
}

上一篇 下一篇

猜你喜欢

热点阅读