Design Pattern

Factory Pattern

Clean Java-only production-ready implementation.


What Problem It Solves

Object creation logic scattered across client code means every new type requires editing multiple call sites. Factory centralizes creation, giving you one place to change when types change.

Naive (Without Factory) โ€” DON'T

if (type.equals("CAR")) spot = new CarSpot();
else if (type.equals("BIKE")) spot = new BikeSpot();
else if (type.equals("TRUCK")) spot = new TruckSpot();

Every if-else chain repeated wherever spots are needed.

Simple Factory vs Factory Method

AspectSimple FactoryFactory Method
StructureOne factory class with a switch/registryAbstract creator with subclass per product
When to useFew product types, stable creationCreation varies per product type
ExtensionAdd to the switch/registryAdd a new Creator subclass
Interview fit90% of LLD problemsUse when different types need different setup

Common Interview Traps

TrapWhyFix
Factory returns null on unknown typeClient forgets null check โ†’ NPEThrow explicit exception or return Optional
Factory depends on concrete typesViolates DIP โ€” factory knows all typesRegistry-based factory avoids switch
Factory does too muchMixes validation, creation, and cachingFactory should only create. Keep it thin.

Where Factory Appears in LLD Problems

ProblemProductFactory
Parking Lot (#1)ParkingSpotParkingSpotFactory.createSpot(type, id)
Chess (#9)ChessPieceChessPieceFactory.createPiece(type, color)
Vending Machine (#7)Product / PaymentProductFactory, PaymentHandlerFactory
Elevator (#3)CommandCommandFactory.create(type, params)
Splitwise (#5)Split StrategySplitStrategyFactory.create(type, amounts)
Notification (#18)ChannelNotificationChannelFactory.create(channelType)

With Factory โ€” DO

// โ”€โ”€โ”€ EXAMPLE 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// WHAT WE ARE IMPLEMENTING:
// A notifications delivery framework routing alerts via Email, SMS, or Push
// channels.
//
// WHERE THE PATTERN FITS IN:
// NotificationFactory acts as the Creator. EmailNotificationFactory and
// SMSNotificationFactory represent Concrete Creators overriding the factory
// method to return matching product subclasses.
// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// --- Products ---
interface ParkingSpot {
    String getId();
    double getHourlyRate();
}

class CarSpot implements ParkingSpot {
    private final String id;
    public CarSpot(String id) { this.id = id; }
    public String getId() { return id; }
    public double getHourlyRate() { return 20.0; }
}

class BikeSpot implements ParkingSpot {
    private final String id;
    public BikeSpot(String id) { this.id = id; }
    public String getId() { return id; }
    public double getHourlyRate() { return 10.0; }
}

class TruckSpot implements ParkingSpot {
    private final String id;
    public TruckSpot(String id) { this.id = id; }
    public String getId() { return id; }
    public double getHourlyRate() { return 40.0; }
}

// --- Factory (centralized creation) ---
enum SpotType { CAR, BIKE, TRUCK }

class ParkingSpotFactory {
    public static ParkingSpot createSpot(SpotType type, String id) {
        return switch (type) {
            case CAR -> new CarSpot(id);
            case BIKE -> new BikeSpot(id);
            case TRUCK -> new TruckSpot(id);
        };
    }
}

// --- Client code ---
public class Main {
    public static void main(String[] args) {
        ParkingSpot carSpot = ParkingSpotFactory.createSpot(SpotType.CAR, "A1");
        ParkingSpot bikeSpot = ParkingSpotFactory.createSpot(SpotType.BIKE, "B2");

        System.out.println("Car spot: " + carSpot.getId() + " Rate: " + carSpot.getHourlyRate());
        System.out.println("Bike spot: " + bikeSpot.getId() + " Rate: " + bikeSpot.getHourlyRate());
    }
}

๐Ÿ’ฌReview

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...