Java - OOPS
Object-Oriented Programming Basics
| Concept | Meaning | Real Elevator Use Case | 
|---|---|---|
| Inheritance | One class derives from another, reusing and extending functionality | Different types of elevators: ExpressElevator,FreightElevatorextendElevator | 
| Interface | A contract defining capabilities without implementation | Movable,Openableactions each elevators has | 
| Abstract Class | Base class with partial implementation and some abstract methods | BaseElevatorclass defines shared logic, but leaves specifics likemove()to subclasses | 
| Polymorphism | Same method behaves differently based on object type | elevator.handleRequest()works differently for express vs standard elevators | 
| Encapsulation | Internal state is hidden, accessed via controlled methods | Elevator's currentFloor,direction, anddoorStatusare accessed via getters/setters | 
| Composition | Building complex objects using other objects | Elevator is composed of Door,Motor | 
Abstract Classes vs Interfaces
Both abstract classes and interfaces help define shared behavior.
- Abstract classes are like partially prepared classes that you extend to create new classes. It has both fields and methods (which can be implemented or unimplemented - abstract methods)
- Interfaces are like contracts that define capabilities without implementation. They define what a class must do, but not how it should do it. It doesn't hold state
Elevator OOP Design
| Class/Component | OOP Concept | Purpose | 
|---|---|---|
| Elevator(abstract) | Abstract class | Provides shared elevator logic and structure | 
| StandardElevator,ExpressElevator | Inheritance | Different elevator behaviors extending base functionality | 
| Door,Motor | Composition | Building blocks that make up a complete elevator | 
| Movable,Openable | Interfaces | Capability contracts for elevator components | 
| ElevatorController | Polymorphism | Manages different elevator types uniformly | 
Abstract Class — Elevator
Base class with partial implementation
public abstract class Elevator {
    // 🟡 State variables - no behaviors.
    // Protected - accessible to child classes
    protected int currentFloor;
    protected Direction direction;
    protected ElevatorState state;
    // 🟡 Compositions
    // These are classes with behaviors (door.open(), motor.start())
    protected final Door door;
    protected final Motor motor;
    protected final ElevatorPanel panel;
    // TreeSet - sorted set. Auto sort on insert
    protected TreeSet<Integer> destinationFloors = new TreeSet<>();
    public Elevator() {
        this.door = new Door();
        // ... initialize variables
        this.currentFloor = 0;
        this.direction = Direction.NONE;
    }
    // 🟡 Abstract methods - each elevator type must implement these
    public abstract void move();
    public abstract void handleRequests();
    // 🟡 Shared method with concrete implementation
    public void pressButton(int floor) {
        destinationFloors.add(floor);
    }
}
Inheritance — Specific Elevators
Different elevator types share core functionality (abstract class) but behave differently (concrete implementation class).
public class StandardElevator extends Elevator {
    @Override
    public void move() {
        // Standard elevator logic
    }
    @Override
    public void handleRequests() {
        // Standard elevators serve all floors
    }
    // automatically inherits pressButton from Elevator
}
public class ExpressElevator extends Elevator {
    @Override
    public void move() {
        // Can skip floors to reach destinations faster
        // Moves the elevator one floor closer to the next destination.
        // Updates elevator direction, and state
    }
    @Override
    public void handleRequests() {
        // Might prioritize express floors or ignore some requests
        // checks whether the elevator has reached a floor someone requested.
        // If yes, 
            // open the door, 
            // removes that floor from the destination list, 
            // and sets the elevator's state to IDLE.
    }
    // automatically inherits pressButton from Elevator
}
Interfaces
Interfaces specify what a class can do, not how it does it.
public interface Movable {
    void move();
}
public interface Openable {
    void open();
    void close();
}
Classes implementing interfaces must provide concrete implementation for the methods
public class Door implements Openable {
    public void open() { // do xyz }
    public void close() { // do abc }
}
ElevatorController - System Orchestrator
It is responsible for coordinating multiple elevators, distributing request to the right elevator and triggering movement.
public class ElevatorController {
    
    // Using Elevator abstract class - we can use any type of elevator
    private final List<Elevator> elevators;
    // Queue to hold incoming floor requests
    // It's possible all elevators are busy, so we need to hold the request
    private final Queue<ElevatorRequest> requestQueue = new LinkedList<>();
    public ElevatorController(List<Elevator> elevators) {
        this.elevators = elevators;
    }
    // Called whenever user presses a button (go to floor 5)
    public void handleRequest(int requestedFloor) {
        requestQueue.add(new ElevatorRequest(requestedFloor));
    }
    
    public void step() {
        processRequests();  // assign pending requests to elevators
        updateElevators();  // let elevators move and process floors
    }
    private void processRequests() {
      // Process all pending requests and try to assign elevator
      Iterator<ElevatorRequest> iterator = requestQueue.iterator();
      while (iterator.hasNext()) {
          ElevatorRequest request = iterator.next();
          Elevator bestElevator = selectElevator(request.floor());
          if (bestElevator != null) {
              bestElevator.pressButton(request.floor());
              iterator.remove();  // remove ONLY when it's been assigned
          }
      }
    }
    private Elevator selectElevator(int requestedFloor) {
      // select the best elevator based on some criteria
    }
    private void updateElevators() {
      for(Elevator elevator : elevators) {
        elevator.handleRequests();  // Check if current floor is a destination
        elevator.move();            // Move one floor if needed
      }
    }
}
// Request to move to a specific floor
public record ElevatorRequest(
    int targetFloor,
    Instant timestamp,
    Priority priority
) {}
Elevator System
public class ElevatorSystem {
  public static void main() {
    List<Elevator> elevators = List.of(
      new StandardElevator(),
      new ExpressElevator()
    );
    ElevatorController controller = new ElevatorController(elevators);
    // Requests come in at different ticks
    controller.handleRequest(5);
    controller.handleRequest(1);
    controller.handleRequest(10);
    // Run simulation
    for(int tick = 0; tick < 10; tick++) {
      controller.step();
    }
  }
}
End to End Flow
User presses button to go to floor 5 → controller.handleRequest(5) → adds to request queue.
tick → controller.step()
processRequests() checks if any elevator can serve the request.
selectElevator(5) → selects the best elevator for floor 5
bestElevator.pressButton(5) → adds to elevator's destinationFloors
Elevator handles requests → elevator.handleRequests() → is current floor a destination? if yes, stop and open the door
Elevator moves → elevator.move() → moves the elevator one floor closer to the next destination