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 , FreightElevator extend Elevator |
Interface | A contract defining capabilities without implementation | Movable , Openable actions each elevators has |
Abstract Class | Base class with partial implementation and some abstract methods | BaseElevator class defines shared logic, but leaves specifics like move() 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 , and doorStatus are 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