Object-Oriented Design: Interview Questions, SOLID Principles & Trade-Offs
Object-oriented design (OOD) questions test your ability to model real-world systems as interacting classes with clear responsibilities. Unlike system design interviews that focus on distributed architecture, OOD interviews focus on class structure, relationships, and extensibility.
SOLID Principles — The Foundation#
Before diving into specific problems, internalize the five SOLID principles. Interviewers expect you to apply them naturally.
Single Responsibility (SRP) — A class should have one reason to change. A ParkingLot class manages spots, not payment processing.
Open/Closed (OCP) — Classes should be open for extension but closed for modification. Add new vehicle types without rewriting the parking logic.
Liskov Substitution (LSP) — Subtypes must be substitutable for their base types. If ElectricCar extends Vehicle, it must work anywhere a Vehicle is expected.
Interface Segregation (ISP) — No client should be forced to depend on methods it does not use. Split a fat Machine interface into Printable, Scannable, and Faxable.
Dependency Inversion (DIP) — Depend on abstractions, not concretions. A PaymentProcessor should depend on a PaymentGateway interface, not directly on StripeClient.
Composition vs Inheritance#
Inheritance creates an is-a relationship. Composition creates a has-a relationship. Prefer composition in most cases:
- Inheritance couples child to parent implementation details. A change in the parent can break all children.
- Composition lets you swap behaviors at runtime by injecting different strategy objects.
- Inheritance hierarchies deeper than two levels become difficult to reason about.
// Inheritance: rigid
class ElectricCar extends Car { ... }
// Composition: flexible
class Car {
private Engine engine; // can be GasEngine, ElectricEngine, HybridEngine
private BrakeSystem brakes;
}
Use inheritance when there is a genuine taxonomic relationship and you want to share interface contracts. Use composition when you want to share behavior.
Design Question 1: Parking Lot#
Requirements: Multi-level parking lot that supports motorcycles, cars, and buses. Different spot sizes. Track availability.
Key classes:
ParkingLot
- levels: List of Level
Level
- spots: List of ParkingSpot
- availableSpots(): int
ParkingSpot
- size: SpotSize (SMALL, MEDIUM, LARGE)
- currentVehicle: Vehicle or null
- canFit(vehicle): boolean
- park(vehicle): void
- remove(): Vehicle
Vehicle (abstract)
- licensePlate: String
- size: VehicleSize
Subtypes: Motorcycle, Car, Bus
Design decisions:
- A
Busneeds multiple contiguousLARGEspots. TheLevelclass handles the search for contiguous spots, not theBusitself (SRP). ParkingSpot.canFit()compares spot size to vehicle size, making it easy to add new vehicle types (OCP).- A
ParkingLotManagercan layer on top to handle entry/exit, ticketing, and payment — separate from the physical lot model.
Design Question 2: Elevator System#
Requirements: Multiple elevators in a building. Handle up/down requests. Optimize for wait time.
Key classes:
ElevatorSystem
- elevators: List of Elevator
- dispatcher: RequestDispatcher
Elevator
- currentFloor: int
- direction: Direction (UP, DOWN, IDLE)
- destinationQueue: PriorityQueue of int
- addDestination(floor): void
- move(): void
RequestDispatcher (interface)
- assignElevator(request): Elevator
Implementations: NearestFirstDispatcher, ZoneBasedDispatcher
Request
- sourceFloor: int
- direction: Direction
Design decisions:
- The
RequestDispatcheris an interface (DIP). You can swap scheduling algorithms without modifyingElevatorSystem. - Each
Elevatormanages its own destination queue using a scan algorithm (serve floors in current direction before reversing). Requestis decoupled fromElevator— the dispatcher decides assignment.
Design Question 3: Library Management#
Requirements: Track books, members, borrowing, and returns. Handle reservations and late fees.
Key classes:
Library
- catalog: Catalog
- members: List of Member
Catalog
- searchByTitle(title): List of Book
- searchByAuthor(author): List of Book
Book
- isbn: String
- title: String
- copies: List of BookCopy
BookCopy
- barcode: String
- status: CopyStatus (AVAILABLE, BORROWED, RESERVED, LOST)
Member
- memberId: String
- borrowedBooks: List of BorrowRecord
- borrow(copy): BorrowRecord
- returnBook(copy): void
BorrowRecord
- copy: BookCopy
- borrowDate: Date
- dueDate: Date
- returnDate: Date or null
- calculateFee(): Money
Design decisions:
- Separate
Book(the title/ISBN) fromBookCopy(the physical item). A library owns multiple copies of the same book. BorrowRecordcalculates late fees (SRP) rather than embedding fee logic inMember.Cataloghandles search, notLibrarydirectly — keeping search indexing separate from membership management.
Design Question 4: Vending Machine#
Requirements: Accept coins and bills. Dispense products. Handle insufficient funds and out-of-stock.
Key classes:
VendingMachine
- state: MachineState
- inventory: Inventory
- paymentCollector: PaymentCollector
MachineState (interface)
- insertMoney(amount): void
- selectProduct(code): void
- dispense(): void
Implementations: IdleState, HasMoneyState, DispensingState
Inventory
- products: Map of String to ProductSlot
- isAvailable(code): boolean
- dispense(code): Product
ProductSlot
- product: Product
- quantity: int
- price: Money
PaymentCollector
- currentBalance: Money
- insert(amount): void
- hasSufficientFunds(price): boolean
- returnChange(price): Money
Design decisions:
- The State pattern models machine behavior. Each state knows which transitions are valid.
IdleStaterejectsdispense()calls;HasMoneyStateallows product selection. InventoryandPaymentCollectorare separate (SRP). The vending machine coordinates them.- Adding new payment methods (e.g., card reader) means implementing a new
PaymentCollectorwithout touchingVendingMachine(OCP, DIP).
Class Diagram Tips#
When drawing class diagrams in an interview:
- Start with nouns from the requirements — they become classes.
- Identify verbs — they become methods.
- Draw relationships — association (has-a), inheritance (is-a), dependency (uses).
- Mark multiplicity — one-to-many, many-to-many.
- Keep it focused — show 5–8 core classes, not every helper.
Use solid arrows for inheritance, dashed arrows for interface implementation, and plain lines with multiplicity labels for associations.
Common Design Trade-Offs#
| Decision | Option A | Option B | Guidance |
|---|---|---|---|
| Inheritance vs Composition | Shared interface contract | Shared behavior, swappable | Prefer composition unless taxonomy is clear |
| Enum vs Subclass | Fixed set of types | Open for extension | Enum for stable sets, subclass for evolving ones |
| Fat class vs Many classes | Fewer files, co-located logic | SRP, easier testing | Split when a class has multiple reasons to change |
| Interface vs Abstract class | Multiple inheritance of type | Shared default behavior | Interface for capability, abstract for family |
Key Takeaways#
- Start every OOD answer by clarifying requirements and identifying core entities.
- Apply SOLID principles throughout — interviewers look for SRP, OCP, and DIP specifically.
- Prefer composition over inheritance for flexibility and testability.
- Use design patterns (State, Strategy, Observer) where they naturally fit, but do not force them.
- Keep class diagrams focused on core relationships — depth over breadth.
- Separate data models from behavior managers. A
Bookstores attributes; aCatalogsearches them.
Build and explore system design concepts hands-on at codelit.io.
258 articles on system design at codelit.io/blog.
Try it on Codelit
90+ Templates
Practice with real-world architectures — Uber, Netflix, Slack, and more
Related articles
Build this architecture
Generate an interactive architecture for Object in seconds.
Try it in Codelit →
Comments