设计电梯

OOD设计流程,以电梯设计为例

『设计电梯类』,每个人对于电梯都有一个具体的认知,但面试者自己的理解是否就和面试官一致呢?避免想当然的去假设,多问问题,明确细节,比如:

  • 电梯的容量(载重,载入数)是否考虑?
  • 电梯的运行范围是几层到几层?
  • 是一部电梯还是多个电梯?

深入分析

当我们相对了解题目的具体需求之后,设计电梯类时要从OO设计基本原则入手,比如封装性,本质上就是讲class内部的状态封装在内,对外提供合理的方法接口。 从方法的角度思考相对直观:根据题目的需求,一个基本的电梯类应该提供什么样的方法呢?

  • 开门、关门
  • 移动到下一目标楼层
  • 接受去目标楼层的请求

以上都是最直观、最基本的方法,相对应的就是电梯内部的基本状态:

  • 电梯门的开关状态 (开关门会影响该状态);
  • 运行方向(移动会影响该状态,该状态也影响下一步行动);
  • 当前楼层 (移动会影响该状态,该状态也影响下一步行动);
  • 需要停的楼层集合(接受去某楼层的请求会影响该状态,该状态影响下一步行动);

Code

public class Elevator{
  private int currentFloor;
  private int targetFloor;
  private int status;
  private static volatile Elevator instance = null;

  private Elevator() {
    this.currentFloor = 0;
    this.targetFloor = 0;
    this.status = 0;
  }

  // 电梯是一个singleton
  public static Elevator getInstance() {
    if (instance == null) {
      Synchronized(this.class) {
        if (instance == null) {
          instance = new Elevator();
        }
      }
    }

    return instance;
  }

  public int getCurrentFloor() {
    return currentFloor;
  }


  public int getStatus() {
    return status;
  }

  public void moveToFloor(int targetFloor) {
    while (currentFloor < targetFloor) {
      moveUp();
    }
    while (currentFloor > targetFloor) {
      moveDown();
    }

    status = 0;
  }

  private void moveUp() {
    status = 1;
    currentFloor += 1;
  }

  private void moveDown() {
    status = -1;
    currentFloor -= 1;
  }
}


public class RequestHandler {
  List<Request> requests;
  private static volatile RequestHandler instance = null;

  public static RequestHandler getInstance() {
    if (instance == null) {
      Synchronized(RequestHandler.class) {
        if (instance == null) {
          instance = new RequestHandler();
        }
      }
    }

    return instance;
  }

  private RequestHandler() {
    requests = new ArrayList<>();
  }


  public addRequest(Request req) {
    Synchronized(req) {
      requests.add(req);
    }
  }

  private Requst getNextRequest() {
    int curentFloor = Elevator.getInstance().getCurrentFloor();
    int shortestdistance = Integer.MAX_VALUE;
    Request next = null;

    for (Request req: requests) {
      if (Math.abs(req.floor - currentFLoor) < shortestdistance) {
        next = req;
      }
    }

    return next;
  }

  public void processRequest() {

    while (true) {
      Request req = getNextRequest();
      if (req != null) {
        while (Elevator.getInstance().getStatus() != 0);
        Elevator.getInstance().moveToFloor(req.getTargetFloor());
        request.remove(req);
      }
    }

  }
}


public class Request {

  private int targetFloor;
  Requst (int targetFloor) {
    this.targetFloor = targetFloor;
  }

  public int getTargetFloor() {
    return targetFloor;
  }
}


public class User{
  public void generateRequset(int targetFloor) {
    RequestHandler.getInstance().addRequest(new Request(targetFloor));
  }
}

results matching ""

    No results matching ""