How to choose design patterns in interviews
A signal-based approach to selecting the right design pattern: recognize the problem shape, match it to a pattern, and justify your choice to the interviewer.
You are fifteen minutes into an LLD round. You have identified the entities, sketched the class diagram, and the interviewer asks: "How would you handle different pricing strategies here?" You freeze. You know Strategy, Factory, Template Method, and a dozen others. But which one fits this problem?
The mistake most candidates make is starting from the pattern catalog and trying to find a place to use each one. That is backwards. Patterns are solutions. You need to start with the problem shape, recognize the signal, and let the signal pick the pattern for you.
This guide gives you the decision-making framework. Not a catalog of patterns (you already have those), but a repeatable process for choosing the right one under interview pressure.
Don't start with patterns
Here is the single most common mistake I see in LLD interviews: candidates walk in with a mental checklist of patterns and spend the first five minutes looking for places to use them. "Where can I put an Observer? Can I force a Singleton somewhere?" That is pattern-first thinking, and it leads to bloated designs that impress nobody.
Patterns exist to solve specific structural problems. If you do not have the problem, you do not need the pattern. Starting with patterns is like walking into a pharmacy and picking medications before you know what is wrong with you.
The right approach is problem-first:
- Identify the entities and relationships in the problem
- Find the variation points where behavior changes based on context
- Name the force that creates the variation (multiple algorithms? states? notifications?)
- Match the force to a pattern using signal recognition
For your interview: never say "I want to use Strategy here." Say "pricing varies by customer tier, so I need to swap algorithms at runtime. Strategy fits." The interviewer hears a reasoned decision, not a memorized playbook.
The bottom line: patterns are consequences of good design decisions, not starting points.
Signal recognition
A "signal" is a structural property of the problem that maps directly to a pattern. When you hear or see certain phrases in the requirements, your brain should light up with the matching pattern. This is not memorization. It is pattern recognition built on understanding why each pattern exists.
The signals and what they mean
| Signal | What you notice | Example in requirements |
|---|---|---|
| Multiple algorithms | Same operation, different strategies | "Support percentage discount, flat discount, and BOGO" |
| State-dependent behavior | Object acts differently based on its current state | "Order can be placed, confirmed, shipped, delivered, or cancelled" |
| Notify on change | When X happens, Y and Z need to know | "Send email AND update dashboard AND log audit trail when payment succeeds" |
| Create without specifying class | Caller should not know which concrete type it gets | "Return the right notification sender based on channel type" |
| Wrap with extras | Add behavior without changing the core | "Add logging, retry, and caching around the HTTP client" |
| Tree of parts | Individual items and groups of items treated the same | "Calculate cost for a single item or a bundle (which contains items and sub-bundles)" |
| Step-by-step template | Same skeleton, different details | "All export formats follow: validate, transform, write. But each format transforms differently." |
| One instance globally | Shared resource across the application | "One connection pool, one configuration registry" |
| Undo/replay | Track actions for reversal or audit | "User can undo the last 5 operations" |
| Simplify a subsystem | Too many classes for the caller to deal with | "The client should not care about parser, validator, and transformer separately" |
I find that in most LLD interviews, three signals dominate: multiple algorithms (Strategy), state-dependent behavior (State), and notify on change (Observer). If you master these three, you cover about 70% of interview scenarios.
The decision matrix
This is the table to internalize. When you spot a signal, look up the pattern and the justification you will give the interviewer.
| Problem signal | Pattern | Core mechanism | Interview justification |
|---|---|---|---|
| Multiple interchangeable algorithms | Strategy | Encapsulate each algorithm behind an interface; swap at runtime | "The algorithms vary independently from the clients that use them" |
| Object behavior depends on current state | State | Each state is a class; transitions delegate to the next state object | "Adding a new state should not require modifying existing state logic" |
| Multiple objects need to react to an event | Observer | Subject maintains a list of listeners; notifies all on change | "Decouples the event source from the event consumers" |
| Need to create objects without specifying the exact class | Factory Method | Subclass or method decides which class to instantiate | "New types can be added without changing creation logic" |
| Add responsibilities dynamically | Decorator | Wrap the original object; each wrapper adds one behavior | "I can compose features without a combinatorial explosion of subclasses" |
| Treat individual and composite objects uniformly | Composite | Component interface; Leaf and Composite both implement it | "Clients do not need to know if they are talking to a leaf or a group" |
| Same algorithm skeleton, varying steps | Template Method | Abstract class defines the skeleton; subclasses override specific steps | "The invariant steps stay in one place; only the variant steps are overridden" |
| Sequential processing with optional steps | Chain of Responsibility | Each handler decides to process or pass to the next | "New handlers can be added without modifying existing ones" |
| Complex object construction | Builder | Step-by-step construction with a fluent API | "Separates construction from representation; avoids telescoping constructors" |
| Control access or add lazy init | Proxy | Same interface as the real object; intercepts calls | "Adds cross-cutting concerns without modifying the real object" |
How to use this in an interview
Do not memorize rows. Instead, practice the recognition loop:
- Read the requirement sentence
- Underline the variation (what changes, what is conditional, what is extensible)
- Match the variation to a signal
- Name the pattern and give the one-sentence justification from the table
Here is a concrete example. The requirement says: "The system should support multiple payment methods: credit card, PayPal, and crypto, with new methods added in the future."
- Variation: payment processing algorithm changes based on method type
- Signal: multiple interchangeable algorithms
- Pattern: Strategy
- Justification: "Payment methods vary independently from the checkout flow that uses them. I will define a
PaymentStrategyinterface and one implementation per method."
That took ten seconds and the interviewer heard a crisp, reasoned answer.
Combining patterns
Real systems rarely use a single pattern in isolation. Interviewers know this. They are impressed when you combine two or three patterns intentionally, not when you pile on patterns for show.
Common pattern combinations
| Combination | Why they pair well | Typical scenario |
|---|---|---|
| Strategy + Factory | Factory picks which Strategy to create; client only knows the interface | "Select the pricing algorithm based on customer tier" |
| State + Strategy | State handles transitions; Strategy handles behavior within a state | "Order state machine where each state has different notification strategies" |
| Observer + Mediator | Observer handles pub/sub; Mediator coordinates complex multi-party interactions | "Chat room where messages fan out and require delivery guarantees" |
| Composite + Iterator | Composite builds the tree; Iterator walks it uniformly | "File system with folders and files; iterate all items regardless of nesting" |
| Builder + Strategy | Builder constructs the object; Strategy configures its runtime behavior | "Build a RetryConfig that accepts different backoff strategies" |
| Template Method + Strategy | Template defines steps; Strategy provides pluggable implementations of specific steps | "All report generators follow the same steps, but formatting is a strategy" |
| Decorator + Factory | Factory creates the base object; Decorators wrap it with features | "Create an HTTP client, then wrap it with logging, retry, and caching" |
Example: Strategy + Factory in Java
This is the most common combination you will reach for. The Factory decides which Strategy to create. The client never touches concrete classes.
// Strategy interface
public interface DiscountStrategy {
Money apply(Money originalPrice, Order order);
}
// Concrete strategies
public class PercentageDiscount implements DiscountStrategy {
private final double rate;
public PercentageDiscount(double rate) { this.rate = rate; }
@Override
public Money apply(Money originalPrice, Order order) {
return originalPrice.multiply(1 - rate);
}
}
public class FlatDiscount implements DiscountStrategy {
private final Money amount;
public FlatDiscount(Money amount) { this.amount = amount; }
@Override
public Money apply(Money originalPrice, Order order) {
return originalPrice.subtract(amount);
}
}
// Factory selects the right strategy
public class DiscountFactory {
public static DiscountStrategy forTier(CustomerTier tier) {
return switch (tier) {
case GOLD -> new PercentageDiscount(0.20);
case SILVER -> new PercentageDiscount(0.10);
case BRONZE -> new FlatDiscount(Money.of(5));
case STANDARD -> order -> order.getTotal(); // no-op
};
}
}
The rule of thumb for combining patterns: if you are using more than three patterns in one design, step back and check if you are over-engineering. Two or three well-chosen patterns is the sweet spot for interviews.
Pattern selection flowchart
When you encounter a variation point in the problem, walk through this decision tree. It will not cover every edge case, but it handles the most common interview scenarios.
I keep this flowchart in my head during interviews. The first three questions (State, Strategy, Observer) handle most cases. If you get past those three and nothing matches, there is a good chance you do not need a pattern at all.
When NOT to use a pattern
This section is as important as knowing which pattern to use. Over-engineering is the #1 criticism interviewers have of LLD candidates who "know too many patterns."
YAGNI: You Ain't Gonna Need It
If there is only one algorithm and the requirements do not mention extensibility, do not use Strategy. If there are only two states with no indication of more, a simple if-else is fine. Patterns add indirection. Indirection has a cost: more classes, more files, harder to trace through.
Signs you are over-engineering
| Red flag | What is happening | What to do instead |
|---|---|---|
| You created an interface with only one implementation | Premature abstraction | Use the concrete class directly |
| Your pattern adds 3+ classes but only handles one scenario | Complexity without payoff | Inline the logic |
| You are using a pattern "because it is a best practice" | Cargo cult design | Ask "what problem does this solve?" |
| The interviewer looks confused by your class diagram | Too many layers of indirection | Simplify. Remove one layer. |
You have a SingletonFactoryStrategyObserverDecorator | Pattern stacking | Step back. Pick the one that matters most. |
The "two implementations" rule
My personal guideline: introduce a pattern interface when you have (or the requirements clearly imply) at least two concrete implementations. One implementation behind an interface is premature. Three implementations behind an interface is a clear signal.
Two is the threshold where the pattern starts earning its keep.
// β Over-engineering: one implementation behind an interface
public interface NotificationSender {
void send(String message);
}
public class EmailSender implements NotificationSender { ... }
// That's it. No SMS, no push. Just email.
// The interface adds indirection for zero benefit.
// β
Justified: multiple implementations exist
public interface NotificationSender {
void send(String message);
}
public class EmailSender implements NotificationSender { ... }
public class SmsSender implements NotificationSender { ... }
public class PushSender implements NotificationSender { ... }
// Now the interface earns its keep.
For your interview: if you can justify the pattern in one sentence ("we need this because X varies"), use it. If you cannot, skip it. Saying "we do not need a pattern here" is a stronger signal than forcing one.
Common mistakes
These are the mistakes I see repeatedly in mock interviews and real rounds. Each one costs points.
Mistake 1: Forcing a pattern where none is needed
The candidate knows Observer exists and adds it to a system where there is exactly one listener. The interviewer asks "why not just call the method directly?" and the candidate has no answer.
Fix: Ask yourself "what would break or become painful if I used a direct method call here?" If the answer is "nothing," skip the pattern.
Mistake 2: Using the wrong pattern
State and Strategy look similar on the surface (both use the same interface-with-implementations structure), but they solve different problems. State handles transitions between behaviors that depend on the object's condition. Strategy handles swappable algorithms chosen by the client.
| Dimension | State | Strategy |
|---|---|---|
| Who triggers the change? | The object itself (internal transition) | The client or factory (external selection) |
| Is there a lifecycle? | Yes, states form a graph with transitions | No, algorithms are independent |
| Can it change at runtime? | Yes, as the object moves through states | Yes, but typically set once at creation |
| Example | Order: PLACED -> CONFIRMED -> SHIPPED | Discount: Percentage, Flat, BOGO |
Fix: If the object changes its own behavior over time through a lifecycle, it is State. If the caller picks one algorithm and sticks with it, it is Strategy.
Mistake 3: Naming classes after patterns
OrderStrategyFactoryObserverImpl tells the interviewer you are thinking about patterns instead of the domain. Name classes after what they represent in the problem domain.
| Bad | Good | Why |
|---|---|---|
PricingStrategy | PricingPolicy | Domain language. "Policy" is what the business calls it. |
OrderStateContext | Order | The Order itself holds state. No need for a separate "context." |
NotificationObserver | AuditLogger | Name what it does, not the pattern role it plays. |
VehicleFactory | VehicleRegistry | If the class does more than creation, name it for its broader role. |
Fix: Name classes after business concepts. If someone who does not know design patterns reads your class name, they should still understand its purpose.
Mistake 4: Applying patterns too early
You are five minutes in. You have barely understood the requirements. And you are already drawing a Decorator chain. The interviewer wanted you to clarify requirements first, then identify entities, and then decide on patterns.
Fix: Follow the OOD interview approach. Patterns come in step 4 or 5, not step 1.
Mistake 5: Not justifying the pattern
Saying "I will use Strategy" is not enough. The interviewer wants to hear why. Every pattern selection needs a one-sentence justification tied to the problem:
- "Pricing algorithms vary by customer tier and we need to add new ones without modifying existing code. Strategy lets me do that."
- "The order moves through a lifecycle where behavior changes at each stage. State encapsulates each stage cleanly."
- "Multiple subsystems need to react when a payment succeeds. Observer decouples the event source from the consumers."
Practice the pattern + justification sentence until it is automatic.
Test Your Understanding
Quick recap
- Start with the problem, not the pattern catalog. Identify variation points first, then select patterns.
- Learn to recognize signals: multiple algorithms (Strategy), state-dependent behavior (State), notify on change (Observer), create without specifying class (Factory).
- Use the decision matrix to connect problem signals to patterns and prepare one-sentence justifications.
- Combine patterns intentionally. Strategy+Factory and State+Strategy are the most common pairs. Two or three patterns is the sweet spot.
- Do not apply patterns unless the problem demands it. One implementation behind an interface is premature. Two or more is justified.
- Name classes after domain concepts, not pattern roles.
PricingPolicybeatsPricingStrategy. - Introduce patterns at step 4 or 5 of the design process, never at step 1.
- Every pattern choice needs a one-sentence justification tied to the specific requirement. "I will use Strategy" is not enough. "Pricing varies by tier, so Strategy" is.