Bird
Raised Fist0

Why Design Patterns Exist and When Not to Use Them

LLDeasyInterview freq: medium
Choose your preparation mode4 modes available
🏗️
Why Design Patterns Exist and When Not to Use Them
Understand the rationale behind design patterns and scenarios where they may be counterproductive
easyDesign Patterns - AppliedFreq: medium
Prerequisites:OOP Basics
⚙️
Functional Requirements
  • Provide Java-specific rationale for design pattern usage
  • Show how abstract classes can hold state unlike interfaces
  • Explain volatile keyword usage in singleton pattern
  • Demonstrate synchronized methods to prevent race conditions
  • Identify when patterns violate Single Responsibility Principle
  • Illustrate composition vs inheritance in pattern relationships
  • Highlight concurrency bugs caused by improper pattern use
👤
Use Cases
  • Explain the purpose of design patterns in Java OOP
  • Identify Java-specific reasons to choose abstract classes over interfaces
  • Demonstrate concurrency-safe pattern implementations
  • Recognize scenarios where patterns introduce unnecessary complexity
  • Discuss SOLID principles in pattern application
  • Evaluate lifecycle ownership in pattern relationships
🧑‍💻
Actors
  • Software Engineer
  • System Architect
  • Code Reviewer
  • Interviewer
❓
Clarifying Questions to Ask
  • How many concurrent threads or actors will interact with the pattern implementations?
  • Is there a pricing or cost strategy influencing pattern choice or complexity?
  • What edge cases exist for pattern misuse or overuse?
  • Are patterns expected to be extended or modified frequently?
  • Should the solution support lazy initialization or eager loading?
  • Is thread safety mandatory for all pattern instances?
Out of Scope
✗ Implementing full design pattern libraries
✗ Discussing patterns unrelated to Java concurrency or OOP
✗ Performance optimization beyond concurrency safety
✗ UI or database integration
⚡
QPS Calculation
write qps100
read qps500
peak qps1000
🖥️
Server Estimate
3
🔢
Enumerations
enum PatternType
CREATIONAL | STRUCTURAL | BEHAVIORAL
Enum prevents typo bugs and enables exhaustive switch statements on pattern categories.
enum UsageRecommendation
RECOMMENDED | AVOID | CONDITIONAL
Encodes when to use or avoid a pattern, enabling clear decision logic and preventing string errors.
📦
DesignPattern
4 fields
private final String nameprivate final PatternType typeprivate final UsageRecommendation usageRecommendationprivate final String javaSpecificRationale
Represents a design pattern with its category, usage advice, and Java-specific reasoning.
public String getName()Returns the pattern's name.
public PatternType getType()Returns the pattern category.
public UsageRecommendation getUsageRecommendation()Returns when to use or avoid the pattern.
public String getJavaSpecificRationale()Returns the Java-specific reasoning behind the pattern.
📦
PatternExample
2 fields
private final DesignPattern patternprivate final String exampleCodeSnippet
Holds a concrete Java code example illustrating the pattern usage.
public DesignPattern getPattern()Returns the associated design pattern.
public String getExampleCodeSnippet()Returns the Java code snippet demonstrating the pattern.
📦
ConcurrencyIssue
3 fields
private final String scenarioDescriptionprivate final String problemDescriptionprivate final String[] solutionCode
Describes a concurrency problem caused by improper pattern use and provides a Java concurrency-safe solution.
public String getScenarioDescription()Returns the concurrency scenario.
public String getProblemDescription()Returns the concurrency problem explanation.
public String[] getSolutionCode()Returns the Java code lines solving the concurrency issue.
📦
LifecycleOwnership
3 fields
private final String ownerClassprivate final String ownedClassprivate final String ownershipType
Defines lifecycle ownership between classes to clarify composition or aggregation.
public String getOwnerClass()Returns the owning class name.
public String getOwnedClass()Returns the owned class name.
public String getOwnershipType()Returns the type of lifecycle ownership.
📦
SOLIDPrinciple
2 fields
private final String nameprivate final String description
Represents a SOLID principle with its name and explanation.
public String getName()Returns the SOLID principle name.
public String getDescription()Returns the principle's detailed explanation.
📦
PatternMisuseScenario
2 fields
private final String misuseDescriptionprivate final String runtimeConsequence
Describes a common Java-specific mistake when misapplying a pattern and its runtime effect.
public String getMisuseDescription()Returns the misuse explanation.
public String getRuntimeConsequence()Returns the runtime consequence of the misuse.
🔗
Relationships
PatternExample──►DesignPattern[many-to-one]
associationPatternExample depends on DesignPattern but DesignPattern can exist independently
DesignPattern──►PatternType[many-to-one]
associationDesignPattern references PatternType enum, which is static and independent
DesignPattern──►UsageRecommendation[many-to-one]
associationDesignPattern references UsageRecommendation enum, independent lifecycle
🗄️
DesignPatterns
PK: pattern_id
pattern_id STRINGname STRINGtype STRINGusage_recommendation STRINGjava_specific_rationale STRING
🗄️
PatternExamples
PK: example_id
example_id STRINGpattern_id STRINGexample_code_snippet STRING
🔌
GetDesignPattern
Request
{
  "pattern_id": "string"
}
Response
{
  "name": "string",
  "type": "string",
  "usageRecommendation": "string",
  "javaSpecificRationale": "string"
}
Fetches details of a design pattern by ID.
🔌
ListPatternExamples
Request
{
  "pattern_id": "string"
}
Response
{
  "examples": [
    {
      "exampleCodeSnippet": "string"
    }
  ]
}
Lists code examples for a given design pattern.
🔌
ReportConcurrencyIssue
Request
{
  "scenarioDescription": "string",
  "problemDescription": "string",
  "solutionCode": [
    "string"
  ]
}
Response
{
  "status": "string"
}
Allows reporting and storing concurrency issues related to patterns.

Practice

(1/5)
1. In the Food Ordering System, the OrderManager class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is this the correct choice?
easy
A. Factory pattern, because it controls object creation centrally.
B. Builder pattern, to construct complex Order objects step-by-step.
C. Singleton pattern, to ensure only one instance manages all orders globally.
D. Prototype pattern, to clone existing OrderManager instances efficiently.

Solution

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

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created and accessed globally.
  2. Step 2: Why Singleton fits this use case

    OrderManager must coordinate all orders centrally to avoid conflicting states; Singleton guarantees a single shared instance.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Private constructor + synchronized static getInstance() -> Singleton pattern [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
2. In designing the Airline Reservation System, should the Seat entity be modeled as an abstract class or an interface, and why?
easy
A. Abstract class, because seats share common state like seat number and class, and behavior like availability checks.
B. Interface, because it allows multiple inheritance and flexible seat type combinations.
C. Interface, because seats only define behavior without any shared state or implementation.
D. Abstract class, because interfaces cannot enforce method signatures for seat operations.

Solution

  1. Step 1: Analyze seat characteristics

    Seats have shared state (seat number, class) and common behavior (availability, booking), which suggests code reuse.
  2. Step 2: Abstract class vs interface

    Abstract class allows shared state and default behavior implementation, while interface cannot hold state and only defines method signatures.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Shared state + behavior -> abstract class [check]
Hint: Shared state needs abstract class, interfaces lack fields [check]
Common Mistakes:
3. To add a new WeekendFeeStrategy pricing rule in the Workflow Engine's fee calculation, which minimal change respects SOLID principles?
medium
A. Modify the existing FeeCalculator class to add weekend logic inside its calculate() method.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy interface and inject it without changing FeeCalculator.
C. Add a boolean flag isWeekend to FeeCalculator and branch logic accordingly.
D. Combine all fee strategies into one large class with if-else for each pricing rule.

Solution

  1. Step 1: Identify SOLID principle involved

    Open-Closed Principle (OCP) requires classes to be open for extension but closed for modification.
  2. Step 2: Apply OCP to fee strategy

    Adding a new WeekendFeeStrategy class extends behavior without modifying existing FeeCalculator, respecting OCP and Dependency Inversion Principle.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New strategy class + no FeeCalculator change -> OCP respected [check]
Hint: OCP: extend with new class, don't modify existing [check]
Common Mistakes:
4. In a parking lot system using the Strategy pattern, if parkVehicle() is NOT synchronized, which exact thread interleaving causes double-booking of the same spot?
medium
A. Thread 1 parks vehicle; Thread 2 waits until Thread 1 finishes, then parks another vehicle.
B. Thread 1 checks spot availability -> true, context switch; Thread 2 checks spot availability -> true; both park simultaneously.
C. Thread 1 parks vehicle; Thread 2 reads spot as occupied and waits.
D. Thread 1 and Thread 2 both crash due to deadlock.

Solution

  1. Step 1: Identify check-then-act race condition

    Without synchronization, Thread 1 reads spot as available but before marking it occupied, context switches to Thread 2 which also reads available.
  2. Step 2: Both threads proceed to park, causing double-booking

    Because the state update is not atomic, both threads believe the spot is free and park simultaneously.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap -> double-booking due to unsynchronized parkVehicle() [check]
Hint: Check availability -> context switch -> both park -> double-booking [check]
Common Mistakes:
5. The system needs to support ElectricCar and ChargingSpot without modifying existing Vehicle or Spot classes. What is the minimum change to support this extensibility in Java?
hard
A. Modify Vehicle class to include a boolean isElectric and add charging logic inside existing methods.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update compatibility map externally.
C. Create a new ElectricVehicle interface and modify Spot to check for it explicitly.
D. Add charging logic inside Vehicle and Spot classes directly, breaking encapsulation.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Enums can be extended with new constants; subclassing ElectricCar adds new behavior without changing Vehicle.
  2. Step 2: Update compatibility externally

    Updating SpotCompatibility.COMPATIBILITY_MAP externally respects OCP and avoids class explosion or god classes.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Extend enums + subclass + external map update -> minimal change [check]
Hint: Extend enums + subclass + external map -> minimal change [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