设计电梯系统
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 是整个电梯系统的核心类,主要有以下几个属性和方法:
![](https://img.haomeiwen.com/i11345146/e3962dee38168c73.png)
属性:
- 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;
}
}