I want to design an elevator system, which has functionality for pressing button from outside of the elevator (Not selecting a direction - Only calls the passenger’s existing floor). And also select floor functionality needed to select a floor for target.
Inside controls have priority over outside controls.
While traveling the elevator only stops a station (via outside control) if it is on its way. I have tried to implement state patterns but it didn't work as I expected.
Can you please put a comment that how can I improve the following solution.
Thanks.
Elevator.java
package OOPDesign.elevatorStates;
import java.util.LinkedList;
import java.util.Queue;
public class Elevator {
public static Elevator instance;
static Queue<Integer> 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<Integer> 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;
}
Test class
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);
}
}
I have tried to implement state patterns but it didn't work as I expected
- could you please clarify what you mean by this? \$\endgroup\$