Skip to content

Latest commit

 

History

History
594 lines (445 loc) · 16.4 KB

File metadata and controls

594 lines (445 loc) · 16.4 KB

🎯 Design Patterns Interview Preparation Guide

A comprehensive guide to ace design pattern interview questions with confidence.

Table of Contents

  1. Most Frequently Asked Patterns
  2. Pattern Comparison Chart
  3. Common Interview Questions
  4. Pattern Selection Guide
  5. Red Flags to Avoid
  6. Interview Tips

Most Frequently Asked Patterns

Top 5 (Asked in 90% of interviews)

  1. Singleton Pattern ⭐⭐⭐⭐⭐

    • Almost guaranteed to be asked
    • Focus on: Thread safety, lazy initialization, alternatives
    • Common question: "How do you prevent multiple instances?"
  2. Factory Pattern ⭐⭐⭐⭐⭐

    • Very common, especially for backend roles
    • Focus on: When to use vs constructors, extensibility
    • Common question: "Difference between Factory and Abstract Factory?"
  3. Observer Pattern ⭐⭐⭐⭐

    • Common for frontend/full-stack roles
    • Focus on: Pub-sub systems, event handlers
    • Common question: "How would you implement a notification system?"
  4. Strategy Pattern ⭐⭐⭐⭐

    • Popular for algorithm-heavy roles
    • Focus on: Runtime behavior change, avoiding conditionals
    • Common question: "Difference between Strategy and State?"
  5. Decorator Pattern ⭐⭐⭐⭐

    • Common across all roles
    • Focus on: Adding functionality dynamically
    • Common question: "How is this different from inheritance?"

Moderately Common (Asked in 40-60% of interviews)

  1. Adapter Pattern ⭐⭐⭐
  2. Facade Pattern ⭐⭐⭐
  3. Builder Pattern ⭐⭐⭐
  4. Command Pattern ⭐⭐⭐
  5. Proxy Pattern ⭐⭐⭐

Pattern Comparison Chart

Quick Reference Table

Pattern Type Problem It Solves When NOT to Use Similar To
Singleton Creational Need exactly one instance Multiple instances are fine None
Factory Creational Complex object creation Simple constructors suffice Abstract Factory
Abstract Factory Creational Create families of related objects Only one product type Factory Method
Builder Creational Complex object with many parameters Simple objects Factory
Prototype Creational Clone expensive objects Creation is cheap None
Adapter Structural Make incompatible interfaces work Interfaces already compatible Bridge
Decorator Structural Add functionality dynamically Static behavior is fine Proxy
Facade Structural Simplify complex subsystem System is already simple Adapter
Proxy Structural Control access to object No access control needed Decorator
Strategy Behavioral Multiple algorithms for same task Only one algorithm State
Observer Behavioral One-to-many notifications No event system needed Mediator
Command Behavioral Parameterize and queue operations Direct method calls work Strategy
State Behavioral Behavior changes with state State doesn't affect behavior Strategy
Template Method Behavioral Algorithm skeleton with variations Algorithm doesn't vary Strategy

Common Interview Questions

🔥 Hot Questions (Practice These!)

Q1: "Tell me about a time you used a design pattern. Why did you choose it?"

Good Answer Structure:

  1. Situation: Describe the problem
  2. Pattern Choice: Explain why you chose this pattern
  3. Implementation: Brief technical details
  4. Result: What improved (maintainability, performance, etc.)

Example:

"In our e-commerce platform, we had 10+ payment methods with complex initialization logic scattered across controllers. I implemented the Factory Pattern to centralize payment gateway creation. This reduced code duplication by 60% and made adding new payment methods trivial—just register a new factory method. When Stripe added Buy Now Pay Later, we integrated it in 30 minutes without touching existing code."

Q2: "What's the difference between Strategy and State patterns?"

Answer:

  • Strategy: Client chooses which strategy to use; strategies are independent
    • Focus: HOW to do something (algorithms)
    • Example: Payment methods (credit card, PayPal, crypto)
  • State: Context automatically changes state; states are interdependent
    • Focus: WHAT state we're in (behavior)
    • Example: Order states (pending → paid → shipped)

Key Insight: "Strategy is about swapping algorithms; State is about swapping behavior based on internal state."

Q3: "When would you NOT use the Singleton pattern?"

Answer: Avoid Singleton when:

  • Testing is important (hard to mock singletons)
  • You need different instances for different contexts
  • The "single instance" requirement might change
  • You're using dependency injection (DI container manages lifecycle)
  • Global state creates hidden dependencies

Better alternatives:

  • Dependency Injection
  • Monostate Pattern
  • Session Scopes

Q4: "How do you make Singleton thread-safe?"

TypeScript Answer:

class Singleton {
  private static instance?: Singleton;
  private static creating = false;

  private constructor() {
    if (Singleton.creating) {
      throw new Error("Use Singleton.getInstance()");
    }
  }

  static getInstance(): Singleton {
    if (!Singleton.instance) {
      Singleton.creating = true;
      Singleton.instance = new Singleton();
      Singleton.creating = false;
    }
    return Singleton.instance;
  }
}

Note: JavaScript/TypeScript is single-threaded, but mention:

  • Double-checked locking (Java/C++)
  • Initialization-on-demand holder idiom
  • Enum singletons (Java)

Q5: "Explain Factory vs Abstract Factory with an example."

Answer:

Factory Method (One product type):

interface Button {
  render(): void;
}

class WindowsButton implements Button {
  render() {
    /* Windows style */
  }
}

class MacButton implements Button {
  render() {
    /* Mac style */
  }
}

class ButtonFactory {
  static create(os: string): Button {
    return os === "windows" ? new WindowsButton() : new MacButton();
  }
}

Abstract Factory (Family of products):

interface UIFactory {
  createButton(): Button;
  createCheckbox(): Checkbox;
}

class WindowsFactory implements UIFactory {
  createButton() {
    return new WindowsButton();
  }
  createCheckbox() {
    return new WindowsCheckbox();
  }
}

class MacFactory implements UIFactory {
  createButton() {
    return new MacButton();
  }
  createCheckbox() {
    return new MacCheckbox();
  }
}

Key Difference: "Factory creates one type; Abstract Factory creates related families."

Q6: "How would you implement an undo/redo feature?"

Answer: Command Pattern

interface Command {
  execute(): void;
  undo(): void;
}

class AddTextCommand implements Command {
  constructor(private editor: Editor, private text: string) {}

  execute() {
    this.editor.addText(this.text);
  }
  undo() {
    this.editor.removeText(this.text);
  }
}

class CommandHistory {
  private history: Command[] = [];
  private current = -1;

  execute(cmd: Command) {
    cmd.execute();
    this.history = this.history.slice(0, this.current + 1);
    this.history.push(cmd);
    this.current++;
  }

  undo() {
    if (this.current >= 0) {
      this.history[this.current--].undo();
    }
  }

  redo() {
    if (this.current < this.history.length - 1) {
      this.history[++this.current].execute();
    }
  }
}

Q7: "What's wrong with this Singleton implementation?"

// Interviewer shows this code
class Singleton {
  static instance = new Singleton();
  constructor() {}
}

Answer: Issues:

  1. ❌ Constructor is public (can create multiple instances)
  2. ❌ Eager initialization (created whether needed or not)
  3. ❌ Can't control initialization timing
  4. ❌ Can't pass parameters to constructor
  5. ❌ No lazy loading

Better:

class Singleton {
  private static instance?: Singleton;
  private constructor() {} // Private!

  static getInstance(): Singleton {
    if (!this.instance) {
      this.instance = new Singleton();
    }
    return this.instance;
  }
}

Q8: "Can you use functional programming instead of patterns?"

Answer: Yes, for many patterns!

Strategy with functions:

// Instead of Strategy classes
type SortStrategy = (arr: number[]) => number[];

const quickSort: SortStrategy = (arr) => {
  /* ... */
};
const mergeSort: SortStrategy = (arr) => {
  /* ... */
};

function sort(arr: number[], strategy: SortStrategy) {
  return strategy(arr);
}

Observer with callbacks:

type Callback = (data: any) => void;

class EventEmitter {
  private listeners: Callback[] = [];

  on(callback: Callback) {
    this.listeners.push(callback);
  }
  emit(data: any) {
    this.listeners.forEach((cb) => cb(data));
  }
}

When OOP patterns are better:

  • Strategies have state
  • Multiple related methods
  • Need inheritance/polymorphism
  • Team prefers OOP

Pattern Selection Guide

Decision Tree

Need to create objects?
├─ YES → Creational Patterns
│   ├─ Only one instance needed? → Singleton
│   ├─ Complex creation logic? → Factory/Builder
│   ├─ Create families of objects? → Abstract Factory
│   └─ Clone expensive objects? → Prototype
│
├─ Need to compose objects/classes?
│   → Structural Patterns
│   ├─ Incompatible interfaces? → Adapter
│   ├─ Add functionality dynamically? → Decorator
│   ├─ Simplify complex system? → Facade
│   └─ Control access? → Proxy
│
└─ Need to define object interactions?
    → Behavioral Patterns
    ├─ Multiple algorithms? → Strategy
    ├─ Notify multiple objects? → Observer
    ├─ Behavior changes with state? → State
    ├─ Parameterize operations? → Command
    └─ Define algorithm steps? → Template Method

By Use Case

Use Case Recommended Pattern
Payment methods Strategy
Logging system Singleton + Strategy
UI component library Factory + Decorator
Event system Observer
API client Singleton + Facade
Database connections Factory + Proxy
Undo/Redo Command
Form validation Strategy + Chain of Responsibility
Authentication Strategy + Decorator
Caching Proxy

Red Flags to Avoid

❌ Things That Make Interviewers Nervous

  1. "I use Singleton for everything"
    • Shows lack of understanding
    • Singletons are often overused
  2. "I memorized all 23 patterns"
    • Interviewer wants practical knowledge
    • Focus on 5-10 most common
  3. "Design patterns solve all problems"
    • Sometimes simple code is better
    • Don't over-engineer
  4. Can't explain WHEN NOT to use a pattern
    • As important as knowing when to use it
  5. Confusing similar patterns
    • Strategy vs State
    • Factory vs Abstract Factory
    • Adapter vs Facade
    • Decorator vs Proxy

✅ Things That Impress Interviewers

  1. "I chose X over Y because..."
    • Shows critical thinking
  2. "Here's a time I refactored to a pattern"
    • Real-world experience
  3. "This pattern has trade-offs..."
    • Understanding limitations
  4. "In JavaScript/TypeScript, I might use..."
    • Language-specific knowledge
  5. "I'd avoid this pattern here because..."
    • Knowing when NOT to use patterns

Interview Tips

📝 Before the Interview

  1. Practice top 5 patterns - Implement from scratch
  2. Know real-world examples - From your projects
  3. Understand trade-offs - Every pattern has drawbacks
  4. Study pattern relationships - How they differ and relate
  5. Review your resume - Be ready to discuss patterns you've used

💬 During the Interview

  1. Ask clarifying questions

    • "What scale are we talking about?"
    • "Are there performance constraints?"
    • "Will this need to be extended?"
  2. Think aloud

    • Explain your reasoning
    • Discuss alternatives
    • Mention trade-offs
  3. Start simple

    • Begin with straightforward solution
    • Then discuss patterns for improvement
    • Don't over-engineer immediately
  4. Draw diagrams

    • UML helps communicate
    • Show relationships
    • Visualize flow
  5. Discuss testing

    • How pattern affects testability
    • Mocking strategies
    • Test examples

🎯 Sample Interview Flow

Interviewer: "Design a notification system that can send emails, SMS, and push notifications."

Good Response:

  1. Clarify (2 minutes)

    • "How many notification types? Will more be added?"
    • "Do we need delivery tracking?"
    • "Any priority or batching requirements?"
  2. Start Simple (3 minutes)

    • "I'll start with a simple interface..."
    interface NotificationService {
      send(recipient: string, message: string): Promise<void>;
    }
  3. Introduce Pattern (5 minutes)

    • "As we add notification types, I'd use the Factory Pattern to handle creation..."
    • Show implementation
    • "We could also use Strategy if we need runtime switching..."
  4. Discuss Extensions (3 minutes)

    • "For retry logic, I'd add Decorator Pattern..."
    • "For delivery tracking, Observer Pattern..."
  5. Address Concerns (2 minutes)

    • "Trade-off: More classes but easier to extend"
    • "Testing: Can mock each service independently"

Pattern Categories Summary

Creational (Object Creation)

  • Singleton: One instance only
  • Factory Method: Create objects via factory
  • Abstract Factory: Create families of objects
  • Builder: Construct complex objects step-by-step
  • Prototype: Clone objects

Structural (Object Composition)

  • Adapter: Make interfaces compatible
  • Bridge: Separate abstraction from implementation
  • Composite: Tree structure of objects
  • Decorator: Add functionality dynamically
  • Facade: Simplified interface
  • Flyweight: Share common data
  • Proxy: Control access

Behavioral (Object Interaction)

  • Chain of Responsibility: Pass request along chain
  • Command: Encapsulate requests
  • Iterator: Traverse collections
  • Mediator: Centralize communication
  • Memento: Save/restore state
  • Observer: Subscribe to events
  • State: Change behavior with state
  • Strategy: Encapsulate algorithms
  • Template Method: Define algorithm skeleton
  • Visitor: Add operations to objects

Final Checklist

Before your interview, make sure you can:

  • Implement top 5 patterns from scratch
  • Explain when NOT to use each pattern
  • Give 2-3 real-world examples per pattern
  • Compare similar patterns (Strategy vs State, etc.)
  • Discuss trade-offs and alternatives
  • Draw UML diagrams for key patterns
  • Explain thread-safety (for Singleton)
  • Discuss testing strategies with patterns
  • Show TypeScript-specific implementations
  • Mention design principles (SOLID)

Resources

Practice

  • Implement patterns in this repository
  • Solve LeetCode design problems
  • Review open-source projects using patterns

Further Reading

  • "Design Patterns" - Gang of Four (Original)
  • "Head First Design Patterns" (Beginner-friendly)
  • Refactoring.Guru (Great visualizations)

Next Steps

  1. Complete all patterns in this repo
  2. Build a real project using 3-5 patterns
  3. Practice explaining patterns to others
  4. Mock interview with peers

Good Luck! 🚀

Remember:

  • Understanding > Memorization
  • Practical > Theoretical
  • Simple > Complex
  • Communication > Perfect Code

You've got this! 💪