Design (LLD)  Lift - Machine Coding

Design (LLD) Lift - Machine Coding

Features Required:

  1. Lift Movement:

    • The lift should move up and down.

    • It should stop at specified floors.

  2. 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.

  3. Internal Logic:

    • The lift should have internal logic to decide its movement based on user requests.
  4. Emergency Handling:

    • There should be a way to handle emergency situations, such as opening the doors manually.
  5. Status Display:

    • Display the current floor and direction of the lift.

Design Patterns Involved or Used:

  1. State Pattern:

    • For representing the different states of the lift (moving up, moving down, stopped).
  2. Strategy Pattern:

    • For defining algorithms to handle user requests and determining the next floor.
  3. Observer Pattern:

    • To notify the lift when a user request is made.
  4. 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);
    }
}

Please note that this is a simplified example, and the logic might need to be adjusted based on the specific requirements and rules of your lift system.

Did you find this article valuable?

Support Subhahu Jain by becoming a sponsor. Any amount is appreciated!