我想设计一个电梯系统,它具有从电梯外部按下按钮的功能(而不是选择一个方向,只打电话给乘客现有的楼层)。还可以选择为目标选择地板所需的地板功能。
内部控件比外部控件具有优先级。
在旅行的时候,电梯只有在途中才能停站(通过外部控制)。我尝试过实现状态模式,但它并没有像我预期的那样起作用。
请您评论一下我如何改进以下解决方案。
谢谢。
Elevator.java
package OOPDesign.elevatorStates;
import java.util.LinkedList;
import java.util.Queue;
public class Elevator {
public static Elevator instance;
static Queue requestQueue;
static ElevatorStateContext elevatorStateContext;
static int currentFloor;
private Elevator(){
requestQueue = new LinkedList<>();
elevatorStateContext = new ElevatorStateContext();
currentFloor = 0;
}
public static Elevator getInstance(){
if(instance == null){
instance = new Elevator();
}
return instance;
}
static void receiveRequest(int passengersFloor){
requestQueue.add(passengersFloor);
processQueue(requestQueue);
}
static void processQueue(Queue requestQueue) {
int passengersFloor = requestQueue.peek();
System.out.println("Currently going "+ passengersFloor);
if(passengersFloor>currentFloor)
elevatorStateContext.setState(State.UP);
else
elevatorStateContext.setState(State.DOWN);
System.out.println("Direction "+ elevatorStateContext.getDirection());
requestQueue.remove();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Arrived "+ passengersFloor);
if(requestQueue.isEmpty()){
elevatorStateContext.setState(State.IDLE);
System.out.println("Direction "+ elevatorStateContext.getDirection());
}
}
}ElevatorControlSystem.java
package OOPDesign.elevatorStates;
public class ElevatorControlSystem {
Elevator elevator;
public ElevatorControlSystem(){
elevator = Elevator.getInstance();
}
void pressButton(int passengersFloor){
dispatchRequest("OUTSIDE",passengersFloor);
}
void selectFloor(int targetFloor){
dispatchRequest("INSIDE",targetFloor);
}
private void dispatchRequest(String priority, int passengersFloor) {
int elevatorFloor = Elevator.currentFloor;
// If elevator is idle it can serve to any request
if(Elevator.elevatorStateContext.getDirection() == State.IDLE){
Elevator.receiveRequest(passengersFloor);
}else {
if (priority == "INSIDE") {
Elevator.receiveRequest(passengersFloor);
} else { // Outside calls
if (Elevator.elevatorStateContext.getDirection() == State.UP && passengersFloor > elevatorFloor) {
Elevator.receiveRequest(passengersFloor);
} else if (Elevator.elevatorStateContext.getDirection() == State.DOWN && passengersFloor < elevatorFloor) {
Elevator.receiveRequest(passengersFloor);
} else {
System.out.println("Can not give service");
}
}
}
}
}ElevatorState.java
package OOPDesign.elevatorStates;
interface ElevatorState {
public State status(ElevatorStateContext ctx);
}ElevatorStateContext.java
package OOPDesign.elevatorStates;
public class ElevatorStateContext {
private State elevatorState;
public ElevatorStateContext(){
elevatorState = State.IDLE;
}
public void setState(State state){
elevatorState = state;
}
public State getDirection(){
return elevatorState;
}
}Enum
package OOPDesign.elevatorStates;
public enum State {
IDLE,
UP,
DOWN;
}测试类
package OOPDesign.elevatorStates;
public class ElevatorTest {
public static void main(String[] args) {
ElevatorControlSystem ecs = new ElevatorControlSystem();
ecs.pressButton(5);
ecs.selectFloor(3);
ecs.pressButton(6);
ecs.selectFloor(1);
ecs.pressButton(9);
ecs.pressButton(10);
ecs.pressButton(11);
}
}发布于 2020-01-01 22:04:19
如果这个设计是为了一个学校的项目,而你已经提交了它,我担心你已经失败了。这个设计很糟糕。
作为指导原则,Java程序应该准确地使用标识符static一次,特别是在声明public static void main(String args[])中。static的任何其他用法都应该发出警告;您可能做错了什么。
考虑一家酒店。它通常有多个电梯。有了static int currentFloor,每部电梯都必须在同一层!有了static ElevatorStateContext elevatorStateContext,所有的电梯都朝同一个方向移动!这是一个糟糕的设计选择。即使只有一个电梯,电梯也应该拥有自己的数据,而不是将其存储为全局类变量。
通常,酒店有多个电梯系统。可能有一个主要的电梯银行,为客人,以及服务电梯为酒店工作人员。酒店的多个塔楼里可能有电梯,还有停车场的电梯。简而言之,可能有多个ElevatorControlSystem,每个人都拥有自己的一套电梯。每次构造ElevatorControlSystem时,它都执行elevator = Elevator.getInstance(); .这意味着每个控制系统都试图操作同一个电梯?
测试if (priority == "INSIDE")正在测试对象标识。只有当存储在String中的priority与嵌入在此编译单元中的String具有相同的标识时,测试才能通过。这是脆弱的,一旦尝试传入在其他地方创建的字符串"INSIDE",就会中断。您应该检查是否相等:if (priority.equals("INSIDE"))。
或者,为INSIDE -vs- OUTSIDE使用一个D19-vs- D20,就像您已经用于电梯状态一样。
ElevatorStateContext包含State elevatorState、setter和getter,它们不添加额外的行为、检查或功能。
这门课的目的是什么?您可以直接在State中存储和获取Elevator,并消除该类。或者应该包括在ElevatorStateContext中的其他东西,比如门是开/开/关/关,还是要求在哪一层?
您有一个队列,它最多只能容纳一个项目。这些行添加项,然后立即取出项进行处理:
requestQueue.add(passengersFloor);
processQueue(requestQueue);在processQueue()中,您可以从队列中分离出peek()和remove()项:
int passengersFloor = requestQueue.peek();
...
requestQueue.remove();
...但是没有必要窥探;您总是删除该项,因此下面的简单代码将起作用:
int passengersFloor = requestQueue.remove();
...您执行elevator = Elevator.getInstance();,但实际上在任何地方都没有使用elevator成员变量。
您可以声明interface ElevatorState,但是从来没有实现过该接口。
操作
由于dispatchRequest()和processQueue()一次只处理一个请求,所以当另一个请求出现时,测试代码完全无法测试运行中的电梯。如果5个人要求电梯在一楼,并进入,并按楼层按钮5,2,6,3,4.
ecs.pressButton(1);
ecs.selectFloor(5);
ecs.selectFloor(2);
ecs.selectFloor(6);
ecs.selectFloor(3);
ecs.selectFloor(4);电梯会移动到5楼,绕过2,3和4。然后它会移动到2楼,绕过4和3。然后它会移动到6楼,绕过3和4。然后它会移动到3楼,绕过4。最后它会移动到4楼。效率太低了。
https://codereview.stackexchange.com/questions/234884
复制相似问题