This I have written as part of my LLD Practice. Please let me know further imporvements that can be done.
Also tell current design is Strong/Average/Lean Hire ?
/*
Design Patterns Used:
- Strategy
- Observer
*//*
Elevator
- User can press button in elevator to reach required destination
- User can call elevator in the direction they want to go
- Elevator should be called based on some strategy
- Upon reaching destination doors should open automatically
*/
import java.util.Arrays;
import java.util.List;
import java.util.Queue;
enum Direction{
UP, DOWN, IDLE
}
enum ElevatorState{
Idle, Moving, Stopped, Maintainance
}
enum DoorState{
Open, Closed
}
abstract class Request{
int floor;
Request(int floor){
this.floor=floor;
}
}
class InternalRequest extends Request{
InternalRequest(int floor){
super(floor);
}
}
class ExternalRequest extends Request{
Direction direction;
ExternalRequest(Direction direction, int floor){
super(floor);
this.direction=direction;
}
}
interface ElevatorObserver{
void onElevatorStateChange(Elevator elevator, ElevatorState elevatorState);
void onElevatorFloorChange(Elevator elevator, int floor);
}
class ElevatorDisplay implements ElevatorObserver{
@Override
public void onElevatorStateChange(Elevator elevator, ElevatorState elevatorState){
}
@Override
public void onElevatorFloorChange(Elevator elevator, int floor){
}
}
interface ElevatorAssignStrategy{
Elevator assignElevator(List<Elevator> elevators, ExternalRequest request);
}
class RoundRobinStrategy implements ElevatorAssignStrategy{
@Override
public Elevator assignElevator(List<Elevator> elevators, ExternalRequest request){
}
}
class Elevator{
String id;
int currFloor;
Direction direction;
DoorState doorState;
ElevatorState elevatorState;
List<ElevatorObserver> observers;
Queue<Request> requests;
void addObserver(ElevatorObserver elevatorObserver){
observers.add(elevatorObserver);
}
void notifyStateChange(){
for(ElevatorObserver obs:observers){
obs.onElevatorStateChange(this,elevatorState);
}
}
void notifyFloorChange(){
for(ElevatorObserver obs:observers){
obs.onElevatorFloorChange(this,currFloor);
}
}
void addRequest(Request request){
requests.offer(request);
processRequests();
}
void processRequests(){
while(!requests.isEmpty()){
Request request= requests.poll();
moveToFloor(request.floor);
}
}
void moveToFloor(int dstFloor){
elevatorState=ElevatorState.Moving;
notifyStateChange();
while(currFloor!=dstFloor){
if(currFloor<dstFloor){
currFloor++;
direction=Direction.UP;
}
else{
currFloor--;
direction=Direction.DOWN;
}
notifyFloorChange();
}
direction=Direction.IDLE;
elevatorState=ElevatorState.Stopped;
notifyStateChange();
openDoor();
closeDoor();
elevatorState=ElevatorState.Idle;
notifyStateChange();
}
void openDoor(){
doorState=DoorState.Open;
}
void closeDoor(){
doorState=DoorState.Closed;
}
}
class ElevatorController{
List<Elevator> elevators;
ElevatorAssignStrategy strategy;
void handleExternalRequest(ExternalRequest request){
Elevator elevator=strategy.assignElevator(elevators,request);
if(elevator!=null) elevator.addRequest(request);
}
void handleInternalRequest(Elevator elevator, InternalRequest request){
elevator.addRequest(request);
}
}
public class Elevator {
public static void main(String[] args) {
Elevator e1=new Elevator();
Elevator e2=new Elevator();
Elevator e3=new Elevator();
ElevatorObserver display=new ElevatorDisplay();
e1.addObserver(display);
e2.addObserver(display);
e3.addObserver(display);
List<Elevator> elevators= Arrays.asList(e1,e2,e3);
ElevatorController controller=new ElevatorController();
controller.handleExternalRequest(new ExternalRequest(Direction.DOWN,3));
controller.handleInternalRequest(new Elevator(),new InternalRequest(4));
}
}