设计电梯
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));
}
}