Features Required:
Lift Movement:
The lift should move up and down.
It should stop at specified floors.
User Interaction:
Users should be able to request the lift at a particular floor.
Users should be able to select the floor they want to go to.
Internal Logic:
- The lift should have internal logic to decide its movement based on user requests.
Emergency Handling:
- There should be a way to handle emergency situations, such as opening the doors manually.
Status Display:
- Display the current floor and direction of the lift.
Design Patterns Involved or Used:
State Pattern:
- For representing the different states of the lift (moving up, moving down, stopped).
Strategy Pattern:
- For defining algorithms to handle user requests and determining the next floor.
Observer Pattern:
- To notify the lift when a user request is made.
Command Pattern:
- For encapsulating a request as an object, thereby allowing for parameterization of clients with different requests, queuing of requests, and logging of the actions.
Diagram
Code: Detailed Implementation
import java.util.ArrayList;
import java.util.List;
// Observer Pattern
interface Observer {
void update(int floor);
}
// State Pattern
interface LiftState {
void handleRequest(Lift lift, int floor);
}
class MovingUpState implements LiftState {
public void handleRequest(Lift lift, int floor) {
if (floor > lift.getCurrentFloor()) {
System.out.println("Moving up to floor: " + floor);
lift.setCurrentFloor(floor);
}
// Change state or stop based on requirements
}
}
class MovingDownState implements LiftState {
public void handleRequest(Lift lift, int floor) {
if (floor < lift.getCurrentFloor()) {
System.out.println("Moving down to floor: " + floor);
lift.setCurrentFloor(floor);
}
// Change state or stop based on requirements
}
}
class StoppedState implements LiftState {
public void handleRequest(Lift lift, int floor) {
System.out.println("Lift is stopped at floor: " + floor);
lift.setCurrentFloor(floor);
// Change state or stop based on requirements
}
}
// Strategy Pattern
interface MovementStrategy {
void move(Lift lift, int floor);
}
class DefaultMovementStrategy implements MovementStrategy {
public void move(Lift lift, int floor) {
lift.setState(new StoppedState());
System.out.println("Lift is stopped at floor: " + floor);
lift.setCurrentFloor(floor);
}
}
class EmergencyMovementStrategy implements MovementStrategy {
public void move(Lift lift, int floor) {
// Emergency movement strategy
}
}
// Command Pattern
interface LiftCommand {
void execute();
}
class RequestCommand implements LiftCommand {
private Lift lift;
private int floor;
public RequestCommand(Lift lift, int floor) {
this.lift = lift;
this.floor = floor;
}
public void execute() {
lift.handleRequest(floor);
}
}
// Lift class
class Lift implements Observer {
private LiftState currentState;
private MovementStrategy movementStrategy;
private int currentFloor;
public Lift() {
this.currentState = new StoppedState();
this.movementStrategy = new DefaultMovementStrategy();
}
public void handleRequest(int floor) {
currentState.handleRequest(this, floor);
move();
}
public void move() {
movementStrategy.move(this, currentFloor);
}
public void update(int floor) {
// Observer pattern update logic
}
public void setState(LiftState state) {
this.currentState = state;
}
public void setMovementStrategy(MovementStrategy strategy) {
this.movementStrategy = strategy;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
}
// LiftController class
class LiftController {
private List<Lift> lifts;
public LiftController(List<Lift> lifts) {
this.lifts = lifts;
}
public void requestLift(int floor) {
// Logic to assign a lift based on the request
if (!lifts.isEmpty()) {
lifts.get(0).handleRequest(floor);
} else {
System.out.println("No lifts available");
}
}
}
public class LiftApp {
public static void main(String[] args) {
Lift lift1 = new Lift();
LiftController liftController = new LiftController(List.of(lift1));
liftController.requestLift(3);
liftController.requestLift(5);
liftController.requestLift(2);
}
}
🔴 Drawbacks and Issues
⚠️ 1️⃣ Concurrency Issues in Handling Multiple Requests
❌ Problem:
If multiple users request the lift at the same time, race conditions can occur.
There is no queueing mechanism to handle concurrent requests.
✅ Solution: Will be covered in our premium course.
⚠️ 2️⃣ Inefficient Lift Movement Decision Logic
❌ Problem:
The lift moves directly to the requested floor without considering optimal routes.
Does not prioritize requests in the same direction, leading to inefficient movement.
✅ Solution: Will be covered in our premium course.
⚠️ 3️⃣ No Emergency Handling Mechanism in Real-Time
❌ Problem:
The EmergencyMovementStrategy class is empty.
No way to manually override lift operations in emergencies.
✅ Solution: Will be covered in our premium course.
Subscribe to our newsletter
Read articles from Low Level Design (LLD) Coding directly inside your inbox. Subscribe to the newsletter, and don't miss out.