Bird
Raised Fist0

Factory Pattern - Object Creation Without Coupling the Caller

LLDeasyInterview freq: high
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
Product abstract class

Product is an abstract class with shared state 'name' and abstract method 'use()'. ConcreteProductA and ConcreteProductB extend Product realizing 'use()'.

🎯 Tests whether candidate knows abstract class is correct here because Product holds instance state 'name' which interfaces cannot hold in Java.
public abstract class Product {
    protected String name;
    public abstract void use();
}
ProductFactory Singleton

ProductFactory is a Singleton with a volatile static instance and synchronized getInstance() method to ensure safe lazy initialization.

🎯 Tests whether candidate states 'volatile on Singleton instance prevents JVM reordering that can expose partially constructed instance'.
public class ProductFactory {
    private static volatile ProductFactory instance;
    private ProductFactory() {}
    public static synchronized ProductFactory getInstance() {
        if (instance == null) {
            instance = new ProductFactory();
        }
        return instance;
    }
Factory method createProduct

ProductFactory has createProduct(String type) method that returns Product instances without exposing concrete classes to Client.

🎯 Tests whether candidate understands Factory Pattern decouples Client from concrete Product classes enforcing Open-Closed Principle (OCP).
    public Product createProduct(String type) {
        if ("A".equals(type)) return new ConcreteProductA();
        else if ("B".equals(type)) return new ConcreteProductB();
        else throw new IllegalArgumentException("Unknown type");
    }
}
Client composition with ProductFactory

Client holds a reference to ProductFactory (association) and calls createProduct to get Product instances, demonstrating loose coupling.

🎯 Tests whether candidate distinguishes association (Client uses ProductFactory) from composition and explains lifecycle independence.
public class Client {
    private ProductFactory factory;
    public Client(ProductFactory factory) {
        this.factory = factory;
    }
    public void doWork() {
        Product p = factory.createProduct("A");
        p.use();
    }
}
📐
Class Diagram
Class Diagram
       +----------------------+
       |      <<Abstract>>     |
       |       Product        |
       +----------------------+
       | - name: String       |
       +----------------------+
       | + use(): void        |
       +----------------------+
               │ extends
       +----------------------+
       | ConcreteProductA     |
       +----------------------+
       |                      |
       +----------------------+
       | + use(): void        |
       +----------------------+
               │ extends
       +----------------------+
       | ConcreteProductB     |
       +----------------------+
       |                      |
       +----------------------+
       | + use(): void        |
       +----------------------+
       +----------------------+
       |    <<Singleton>>     |
       |   ProductFactory     |
       +----------------------+
       | - volatile instance: |
       |   ProductFactory     |
       +----------------------+
       | + getInstance():     |
       |   ProductFactory     |
       |   [sync]             |
       | + createProduct(type:|
       |   String): Product   |
       +----------------------+
               │ composition
       +----------------------+
       |       Client         |
       +----------------------+
       | - factory: ProductF. |
       +----------------------+
       | + doWork(): void     |
       +----------------------+

This diagram illustrates the Factory Pattern with a Singleton ProductFactory that creates Product instances without coupling the Client to concrete classes. Product is an abstract class holding shared state 'name' and abstract behavior 'use()', which ConcreteProductA and ConcreteProductB realize. ProductFactory uses a volatile static instance and synchronized getInstance() method to ensure thread-safe lazy initialization, preventing JVM reordering bugs. The createProduct method encapsulates object creation, enforcing the Open-Closed Principle by allowing new products without modifying Client code. Client holds an association to ProductFactory, showing lifecycle independence and loose coupling. These Java-specific design decisions ensure extensibility, thread safety, and maintainability.

Primary Focus

✓ Factory Pattern decoupling + Singleton volatile usage + Inheritance vs Realization + Composition lifecycle

Practice

(1/5)
1. In designing a Command interface in Java, should it be an abstract class or an interface, and why? Consider that commands may need to store state for undo functionality.
easy
A. Abstract class, because it allows sharing common state and default undo logic among commands
B. Abstract class, because interfaces cannot declare methods
C. Interface, because Java interfaces can have default methods to share code and state
D. Interface, because commands only declare behavior and state should be external

Solution

  1. Step 1: Analyze state requirements for undo

    Commands often need to store state (e.g., previous values) to support undo, which requires fields.
  2. Step 2: Compare interface vs abstract class in Java

    Interfaces cannot hold instance fields, so abstract classes are better to share common state and default undo logic.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Abstract class supports shared state and behavior for undo [check]
Hint: Use abstract class for shared state in commands [check]
Common Mistakes:
2. In the Stack Overflow design, the Vote class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is this the correct use case?
easy
A. Factory pattern, because it controls object creation with parameters
B. Prototype pattern, to clone existing Vote instances for performance
C. Singleton pattern, to ensure only one Vote manager instance handles voting logic
D. Builder pattern, to incrementally construct Vote objects with complex state

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created and accessed thread-safely.
  2. Step 2: Why Singleton fits Vote manager

    Vote management requires a single point of control to maintain consistent vote counts and prevent conflicting updates, which Singleton enforces.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton [check]
Hint: Private constructor + static synchronized getInstance() -> Singleton [check]
Common Mistakes:
3. A class has a private constructor and a static synchronized getInstance() method that returns the single instance. Which design pattern is applied and why is this the CORRECT use case?
easy
A. Factory Pattern, because it controls object creation centrally.
B. Prototype Pattern, because it clones existing instances to avoid new creation.
C. Builder Pattern, because it constructs complex objects step-by-step.
D. Singleton Pattern, because it ensures only one instance with thread-safe lazy initialization.

Solution

  1. Step 1: Identify the pattern from private constructor and static synchronized method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created lazily and safely in multithreaded contexts.
  2. Step 2: Eliminate other creational patterns

    Factory controls creation but allows multiple instances; Builder separates construction steps; Prototype clones instances. None enforce single instance with thread safety.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Private constructor + synchronized getInstance() -> thread-safe Singleton [check]
Hint: Private constructor + synchronized getInstance() -> Singleton [check]
Common Mistakes:
4. You want to add a WeekendFeeStrategy to calculate parking fees differently on weekends. According to SOLID principles, what is the minimum change required in the current Abstract Factory design?
medium
A. Add a boolean weekend flag to ParkingLot and modify fee calculation accordingly.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes.
C. Combine all fee strategies into one class with multiple methods for each pricing rule.
D. Modify the existing FeeStrategy class to add weekend logic with if-else checks.

Solution

  1. Step 1: Identify SOLID principle involved

    Open-Closed Principle (OCP) requires new functionality added via extension, not modification.
  2. Step 2: Evaluate options

    Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes. respects OCP by adding a new class without modifying existing ones. Add a boolean weekend flag to ParkingLot and modify fee calculation accordingly. modifies ParkingLot, violating OCP. Options A and D modify existing classes, violating OCP.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class added, existing classes unchanged [check]
Hint: OCP: extend with new class, don't modify existing ones [check]
Common Mistakes:
5. In a multi-threaded Java implementation of a parking lot using the Template Method pattern, the parkVehicle() method checks if a spot is available before assigning it. Without synchronization, which exact thread interleaving causes double-booking of the same spot?
medium
A. Thread 1 and Thread 2 both call parkVehicle() simultaneously and block each other.
B. Thread 1 releases a spot while Thread 2 is assigning, causing inconsistent state but no double-booking.
C. Thread 1 assigns spot, then Thread 2 checks availability and finds it occupied, so no double-booking.
D. Thread 1 checks isAvailable() -> true, context switch; Thread 2 checks isAvailable() -> true; both assign the same spot.

Solution

  1. Step 1: Trace check-then-act race

    Thread 1 calls isAvailable() and sees true, but before assigning, context switches.
  2. Step 2: Thread 2 also calls isAvailable() and sees true, then both assign the same spot concurrently.

  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Unsynchronized check-then-act allows double assignment [check]
Hint: Check-then-act without sync -> double booking [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard