---
title: Design Patterns Interview Questions and Answers (2026)
description: The design patterns interview questions that actually come up in 2026 — Singleton, Factory, Observer, Strategy, Decorator and more — with real answers, code, and when each pattern is actually the right call.
url: https://usegreenroom.app/blog/design-patterns-interview-questions
last_updated: 2026-06-23
---

← Back to blog

CS Fundamentals

# Design patterns interview questions

June 23, 2026 · 20 min read

![Design patterns interview questions and answers — cover from Greenroom, the AI mock interviewer](/assets/blog/design-patterns-interview-questions-hero.webp)

There's a specific kind of interview silence that happens when someone asks "can you explain the Singleton pattern?" and the candidate launches into a flawless, word-perfect definition — then gets asked "okay, where have you actually used one?" and the room goes quiet enough to hear the interviewer's coffee cooling. You memorized the Gang of Four book's table of contents at 1am the night before. You can recite "ensures a class has only one instance and provides a global point of access to it" in your sleep. You have never, not once, used this in a real codebase, and it shows in about four seconds.

Design patterns interviews reward something narrower and more useful than memorization: recognizing *which problem* a pattern solves, recognizing when you're looking at that problem in unfamiliar code, and — just as often — recognizing when reaching for a named pattern is overkill for a problem three lines of straightforward code would solve better. This guide covers the **design patterns interview questions** that actually come up in 2026 — creational, structural, and behavioral patterns, SOLID principles, real code, and the anti-pattern traps interviewers specifically probe for — organized by category, with a real answer and a worked code example for each one.

## What a design patterns interview actually tests

### Why do companies still ask about design patterns when most code doesn't name-drop them?

Because the patterns are a shared vocabulary for problems that recur constantly, even when nobody calls them by their Gang of Four name. Nobody on your team says "let's apply the Observer pattern here" out loud — they say "let's make the UI re-render when the data changes," and that *is* Observer, whether or not anyone names it. Interviewers ask pattern questions because the names compress a lot of design reasoning into a quick shorthand: if you can correctly map "I need to notify several unrelated parts of the app when one thing changes" to "Observer," you've demonstrated you can spot a recurring shape in a problem instead of solving every problem from first principles every time. That pattern-recognition skill, not the vocabulary itself, is what's being tested.

### Do I need to memorize all 23 Gang of Four patterns?

No — and claiming you have, then fumbling the third follow-up question, is worse than honestly knowing eight well. Interviewers in practice ask about a recurring core: Singleton, Factory (Simple Factory and Factory Method), Builder, Observer, Strategy, Decorator, Adapter, and increasingly Dependency Injection as a pattern in its own right even though it's not in the original GoF book. Know those eight cold — what problem each solves, when each is the wrong choice, and a real or realistic code example — and you'll handle the large majority of pattern questions asked in 2026 interviews. The remaining patterns (Command, Visitor, Flyweight, Mediator, Chain of Responsibility, and so on) are worth a one-sentence mental model each, not deep fluency, unless the role specifically touches the domain where they're common (game engines for Flyweight, undo/redo systems for Command).

### Are design pattern questions different at junior vs. senior levels?

Sharply, yes. At junior level, interviewers want correct definitions and a basic implementation — can you write a Singleton, can you explain why Factory exists instead of calling constructors directly. At senior level, the bar shifts almost entirely to judgment: "when would you *avoid* this pattern," "what's the cost of over-applying Singleton," "how would you refactor this overly-abstracted code that uses four patterns where one would do." Senior candidates who only prepared definitions get caught flat by the second half of every question — the "and when is this the wrong call" half — because that's where the real signal is.

## Creational pattern questions

### Explain the Singleton pattern. What's it actually good for, and why does it have a bad reputation?

Singleton ensures a class has exactly one instance for the lifetime of the application, with a single global access point to it — useful for things that are genuinely singular by nature: a logging service, a connection pool, an application-wide configuration object. Its bad reputation comes from overuse: Singleton is effectively global mutable state with a design-pattern name attached, which makes unit testing harder (you can't easily swap in a mock instance), introduces hidden coupling (any code can reach into the singleton from anywhere, with no visible dependency in a function's signature), and complicates concurrency if multiple threads access it without proper synchronization. The senior-level answer names this tradeoff unprompted: "I'd reach for Singleton only for genuinely single-per-process resources, and even then I'd usually prefer passing the instance explicitly via dependency injection rather than letting code reach for a global — it's the same single-instance guarantee with far better testability."

```js
class Logger {
  static #instance;
  #logs = [];

  static getInstance() {
    if (!Logger.#instance) {
      Logger.#instance = new Logger();
    }
    return Logger.#instance;
  }

  log(message) {
    this.#logs.push({ message, time: Date.now() });
  }
}

// Anywhere in the app, the same instance is returned:
Logger.getInstance().log('Server started');
```

### What's the difference between the Factory Method pattern and a Simple Factory?

A **Simple Factory** is a single function or static method that takes a type parameter and returns the right object — a pragmatic, common pattern that isn't actually one of the 23 GoF patterns, just a useful convention. The **Factory Method** pattern is more structured: a base class defines an abstract method for creating objects, and subclasses override it to produce different concrete types — the creation logic itself becomes polymorphic, not just a switch statement. The practical difference shows up when new types are added often: Simple Factory means editing one growing switch statement every time, while Factory Method means adding a new subclass without touching existing code — directly serving the Open/Closed Principle. The interview-ready answer: reach for Simple Factory when the type set is small and stable; reach for Factory Method when you expect the type set to grow and want new types added without modifying existing creation logic.

```js
// Factory Method: each subclass owns how it creates its own report
class ReportGenerator {
  createReport() {
    throw new Error('Subclasses must implement createReport()');
  }
}

class PDFReportGenerator extends ReportGenerator {
  createReport() { return new PDFReport(); }
}

class CSVReportGenerator extends ReportGenerator {
  createReport() { return new CSVReport(); }
}

// Adding a new format means adding a new subclass, not editing a switch statement.
```

### Explain the Builder pattern, and when it's worth the extra code.

Builder separates the construction of a complex object from its final representation, letting you build the object step by step through a fluent chain of method calls instead of one constructor with eight optional parameters. It's worth the extra code specifically when an object has many optional fields and constructor overloading would otherwise spiral into an unreadable mess — the classic "telescoping constructor" anti-pattern, where you end up with five overloaded constructors just to cover different combinations of optional arguments. It's *not* worth it for objects with two or three simple fields — that's reaching for ceremony the problem doesn't need, and a sharp interviewer will ask exactly that follow-up to see if you over-apply patterns reflexively.

```js
class HttpRequestBuilder {
  #request = { headers: {}, method: 'GET' };

  setUrl(url) { this.#request.url = url; return this; }
  setMethod(method) { this.#request.method = method; return this; }
  setHeader(key, value) { this.#request.headers[key] = value; return this; }
  build() { return { ...this.#request }; }
}

const req = new HttpRequestBuilder()
  .setUrl('/api/users')
  .setMethod('POST')
  .setHeader('Content-Type', 'application/json')
  .build();
```

### What problem does Dependency Injection solve, and how does it relate to Factory?

Dependency Injection (DI) gives an object its dependencies from the outside (via constructor, method, or a DI container) rather than letting the object construct or look up its own dependencies internally. The problem it solves is tight coupling and poor testability: a class that internally does `new PostgresDatabase()` can never be tested against a fake database without touching a real one, while a class that receives a `database` object through its constructor can be handed a mock in tests and a real connection in production, with zero code changes. DI and Factory frequently work together — a factory or DI container is often *what produces* the dependency that then gets injected — but they solve different halves of the problem: Factory decides *what* concrete object to create; DI decides *how* that object gets handed to the code that needs it, rather than the consuming code reaching out and constructing it directly.

<div class="verdict"><strong>The thread through every creational pattern:</strong> they all exist to decouple "what gets created" from "how it gets used." The interview question behind every creational-pattern question is really: does this code know too much about how to build its own dependencies?</div>

## Structural pattern questions

### Explain the Adapter pattern with a real-world example.

Adapter converts the interface of one class into an interface another part of your code expects, letting otherwise-incompatible interfaces work together without modifying either one. The textbook real-world example: a phone charger adapter that lets a US plug fit a European socket — neither the plug nor the socket changes, a third piece in between translates. In code, this shows up constantly when integrating a third-party library or legacy code whose method names and shapes don't match what your application expects: you wrap the third-party object in an adapter class that exposes the interface your code wants, while internally calling the third-party library's actual methods. This is also exactly the shape of a payment-gateway integration layer — your checkout code calls `charge(amount)` on an internal interface, and a Stripe adapter and a Razorpay adapter each translate that into their own SDK's specific method calls.

```js
// Your app's expected interface
class PaymentProcessor {
  charge(amountInCents) { throw new Error('not implemented'); }
}

// Third-party SDK has a totally different shape you don't control
class LegacyStripeSDK {
  makePaymentInDollars(dollars, currency) { /* ... */ }
}

// Adapter translates between them
class StripeAdapter extends PaymentProcessor {
  #sdk = new LegacyStripeSDK();
  charge(amountInCents) {
    return this.#sdk.makePaymentInDollars(amountInCents / 100, 'USD');
  }
}
```

### What's the difference between Adapter and Decorator? Candidates mix these up constantly.

Both wrap an object, which is exactly why they're confused — but they wrap for opposite reasons. **Adapter** changes an interface to match what the caller expects, without adding new behavior — same functionality, different shape. **Decorator** keeps the same interface but adds new behavior or responsibility on top of the wrapped object, and decorators can be stacked, each adding one more layer of behavior. The clean test interviewers want you to apply on the spot: "is this wrapper changing what the interface looks like, or changing what it does while keeping the same shape?" Adapter changes the shape; Decorator changes the behavior.

```js
// Decorator: same interface (a coffee with a cost), stacked behavior
class Coffee {
  cost() { return 2; }
}

class MilkDecorator {
  #coffee;
  constructor(coffee) { this.#coffee = coffee; }
  cost() { return this.#coffee.cost() + 0.5; }
}

class SyrupDecorator {
  #coffee;
  constructor(coffee) { this.#coffee = coffee; }
  cost() { return this.#coffee.cost() + 0.7; }
}

const order = new SyrupDecorator(new MilkDecorator(new Coffee()));
order.cost(); // 3.2 — each layer adds behavior without changing the interface
```

### Explain the Facade pattern, and how it's different from just "writing a helper function."

Facade provides a simplified, unified interface to a complex subsystem made of multiple classes with their own interdependencies — hiding that complexity behind one clean entry point so callers don't need to understand or coordinate the subsystem's internals. The honest distinction from "just a helper function": a helper function usually wraps one operation, while a Facade specifically sits in front of a *subsystem* — several collaborating classes — and its real value is reducing coupling between the calling code and that whole subsystem, not just saving a few lines. A video-conversion module is the classic example: codecs, bitrate settings, audio mixing, and file I/O are all separate complex pieces, and a `VideoConverter.convert(file, format)` facade hides all of it behind one call.

### What's the Decorator pattern's relationship to middleware, and why does this matter for backend interviews?

Express, Koa, and most backend middleware chains are Decorator in practice, even though nobody calls them that in the documentation: each middleware function wraps the next handler, optionally adding behavior before and after calling it, and middleware stack the same way decorators stack — the request passes through layer after layer, each adding logging, auth checks, or response shaping, without any layer needing to know about the others. Recognizing this connection is a strong interview signal specifically because it shows you can map a pattern's abstract definition onto code you've actually written, rather than only being able to recognize the pattern in a textbook example built to illustrate it cleanly.

## Behavioral pattern questions

### Explain the Observer pattern, and name a system you've used that's built on it.

Observer defines a one-to-many dependency between objects: when a "subject" object's state changes, all of its registered "observers" get notified automatically, without the subject needing to know any specifics about what each observer does with that notification. React's state updates, event listeners in any UI framework, and pub/sub messaging systems are all Observer in practice — a component subscribes to a piece of state, and re-renders when that state's owner notifies it of a change, with the state owner having zero knowledge of which components are listening. The interview-ready follow-up: "what goes wrong with Observer at scale?" — too many observers on one subject can create performance problems (a single change fanning out to hundreds of notified listeners), and badly managed subscriptions create memory leaks when observers are never unregistered, which is exactly why `useEffect` cleanup functions and explicit `removeEventListener` calls exist.

```js
class EventEmitter {
  #listeners = {};

  on(event, callback) {
    (this.#listeners[event] ??= []).push(callback);
  }

  emit(event, data) {
    (this.#listeners[event] ?? []).forEach((cb) => cb(data));
  }
}

const bus = new EventEmitter();
bus.on('order:placed', (order) => console.log(`Notify warehouse: ${order.id}`));
bus.on('order:placed', (order) => console.log(`Send confirmation email: ${order.id}`));
bus.emit('order:placed', { id: 'A1001' }); // both listeners fire, independently
```

### Explain the Strategy pattern, and how it's different from just using an if/else chain.

Strategy defines a family of interchangeable algorithms, encapsulates each one behind a common interface, and lets the algorithm be swapped at runtime without changing the code that uses it. The difference from an if/else or switch statement isn't capability — both can pick between behaviors — it's *extensibility and isolation*: adding a new strategy means adding a new class that implements the shared interface, with zero changes to existing code, while adding a new branch to an if/else chain means editing a function that already works, risking regressions in the branches you didn't touch. Strategy is also far easier to unit test in isolation — each strategy is its own class you can test independently, while a giant if/else chain has to be tested as one entangled unit. The honest caveat interviewers want named: for two or three stable, simple cases that will basically never grow, an if/else is genuinely simpler and Strategy is unnecessary ceremony — reach for it when the algorithm set is expected to grow, or when each branch is complex enough to deserve its own isolated test.

```js
// Strategy: pluggable pricing rules, swappable at runtime
class RegularPricing { calculate(price) { return price; } }
class StudentDiscountPricing { calculate(price) { return price * 0.9; } }
class BlackFridayPricing { calculate(price) { return price * 0.5; } }

class Checkout {
  #strategy;
  setStrategy(strategy) { this.#strategy = strategy; }
  total(price) { return this.#strategy.calculate(price); }
}

const checkout = new Checkout();
checkout.setStrategy(new BlackFridayPricing());
checkout.total(100); // 50 — swap the strategy, behavior changes, no if/else
```

### What is the Command pattern, and where does it actually show up in real software?

Command encapsulates a request — an action plus the data it needs — as a standalone object, so the action can be queued, logged, undone, or executed later instead of being called directly and immediately. It shows up most visibly in undo/redo systems (each user action becomes a Command object pushed onto a history stack, and undo simply calls the inverse operation on the most recent one), task queues and job schedulers (a job is a Command object that gets serialized, queued, and executed by a worker later, possibly on a different machine), and GUI button/menu actions, where the same "Save" command object can be triggered from a toolbar button, a keyboard shortcut, or a menu item without duplicating the save logic three times.

### Explain the Observer vs. pub/sub distinction interviewers sometimes probe.

Classic Observer is typically tight and direct: the subject holds a list of its observers and calls them directly, and observers usually know they're observing one specific subject. **Pub/sub** (publish/subscribe) decouples further by routing through a separate broker or event bus: publishers emit events to named channels/topics without knowing who, if anyone, is listening, and subscribers register interest in a topic without knowing who publishes to it. The practical difference matters at scale — pub/sub scales better across services and processes (publishers and subscribers don't need direct references to each other, which is exactly why message queues like Kafka or RabbitMQ exist), while classic Observer is simpler and fine within a single process or a single class's well-defined notification list. Interviewers who ask this are checking whether you understand Observer isn't just "the basis of event listeners" but a spectrum that includes distributed pub/sub systems at the far end.

![A diagram comparing the most commonly asked design patterns, grouped by category and what each solves](/assets/blog/design-patterns-interview-questions-diagram.webp)

Knowing which bucket a pattern lives in — creational, structural, behavioral — is half of answering "which pattern fits this problem" fast.

### Explain the Template Method pattern, and how it differs from Strategy.

Template Method defines the skeleton of an algorithm in a base class — the fixed sequence of steps — while letting subclasses override specific steps without changing the overall structure. It's easy to confuse with Strategy because both vary behavior, but the mechanism is opposite: Template Method uses **inheritance** (subclasses override individual steps of one fixed algorithm shape), while Strategy uses **composition** (entire interchangeable algorithm objects, swapped in from outside, with no inheritance relationship required between them). A data-import pipeline is a clean example of Template Method: `readFile()`, `validate()`, `transform()`, `save()` always run in that order, but a CSV importer and a JSON importer override `readFile()` and `transform()` differently while sharing the same overall flow. The interview tell: if the *steps themselves* vary but the *order* is fixed, that's Template Method; if the *entire algorithm* is swappable as one unit, that's Strategy.

```js
class DataImporter {
  // The template — fixed order, cannot be changed by subclasses
  run(source) {
    const raw = this.readFile(source);
    const valid = this.validate(raw);
    const transformed = this.transform(valid);
    return this.save(transformed);
  }
  validate(data) { return data.filter(Boolean); } // shared default
  save(data) { return db.insert(data); }            // shared default
}

class CSVImporter extends DataImporter {
  readFile(source) { return parseCSV(source); }
  transform(data) { return data.map(toRecord); }
}

class JSONImporter extends DataImporter {
  readFile(source) { return JSON.parse(source); }
  transform(data) { return data; } // already shaped correctly
}
```

### What is the Chain of Responsibility pattern, and where does it show up in backend systems?

Chain of Responsibility passes a request along a chain of handler objects, where each handler decides either to process the request or pass it to the next handler in the chain, without the caller needing to know which handler will ultimately deal with it. It shows up constantly in backend middleware and validation pipelines: an incoming request might pass through an auth-check handler, then a rate-limit handler, then a request-validation handler, then finally the actual route logic — each one able to short-circuit the chain (reject the request) or pass it forward. The distinction from Decorator, which it superficially resembles (both chain wrapped behavior): Decorator's whole point is that *every* layer runs and adds behavior; Chain of Responsibility's whole point is that the chain can stop early, and typically only one handler actually "handles" the request rather than all of them contributing.

```js
class Handler {
  #next;
  setNext(handler) { this.#next = handler; return handler; }
  handle(request) {
    if (this.#next) return this.#next.handle(request);
    return null;
  }
}

class AuthHandler extends Handler {
  handle(request) {
    if (!request.token) return { error: 'Unauthorized' };
    return super.handle(request);
  }
}

class RateLimitHandler extends Handler {
  handle(request) {
    if (request.tooManyRequests) return { error: 'Rate limited' };
    return super.handle(request);
  }
}

const chain = new AuthHandler();
chain.setNext(new RateLimitHandler());
chain.handle({ token: 'abc', tooManyRequests: false }); // passes through, reaches the end
```

## SOLID principles questions

### Walk through SOLID and how each principle connects to a pattern above.

**Single Responsibility** — a class should have one reason to change, one job. It underlies why Strategy pulls algorithm variants out into their own classes instead of bloating one class with every variant's logic. **Open/Closed** — software should be extendable without modifying existing, working code. Factory Method and Strategy both serve this directly: adding a new report type or pricing rule means adding a new class, not editing one that already works. **Liskov Substitution** — a subclass should be usable anywhere its parent class is expected, without breaking behavior; this is the quiet rule that makes Decorator and Adapter work at all, since both rely on substitutability of the wrapped object for the original interface. **Interface Segregation** — prefer several small, specific interfaces over one large general-purpose one, so implementers aren't forced to implement methods they don't need. **Dependency Inversion** — high-level code should depend on abstractions, not concrete implementations; this is the principle Dependency Injection exists to satisfy in practice.

### What's a real example of violating Liskov Substitution, and why does it matter?

The classic example: a `Square` class that extends `Rectangle` and overrides `setWidth`/`setHeight` to keep both sides equal — this looks reasonable until code that works correctly with any `Rectangle` (set width to 5, set height to 10, expect area 50) silently breaks when handed a `Square`, because setting one side changed the other unexpectedly. It matters because LSP violations don't throw an error — they produce *quietly wrong behavior* in code that was written correctly against the parent type's contract, which is exactly the kind of bug that's miserable to track down in production because nothing crashes, a value is just wrong. The fix is usually rethinking the inheritance relationship itself — a Square isn't really an "is-a" Rectangle in terms of behavioral contract, even though it is geometrically.

### How does Interface Segregation show up in a language without traditional interfaces, like JavaScript or Python?

The principle still applies even without a formal `interface` keyword — it shows up as "don't design one giant class or object contract that forces every implementer to support methods most of them don't need." In practice: instead of one bloated `Worker` base class with `cook()`, `clean()`, `deliver()`, and `manage()` that every subclass has to implement (and stub out with "not applicable" for roles that don't do all four), split into smaller role-specific contracts — a `Cook`, a `Cleaner`, a `Deliverer` — and compose objects from the roles they actually fulfill. Python's duck typing and JS's structural typing make this even more natural: you're not violating an explicit `interface` keyword, but you're still creating the same maintenance pain of unrelated responsibilities forced into one bloated contract.

## When NOT to use a pattern — the question that separates strong candidates

### What's "pattern overuse," and why do senior interviewers specifically probe for it?

Pattern overuse is applying a named pattern because it sounds sophisticated or because a tutorial used it for a similar-looking problem, not because the actual codebase has the specific complexity the pattern exists to manage — three layers of Decorator wrapping a function that never needed more than an if statement, or a Factory Method hierarchy for a type set that has had exactly two members for three years and shows no sign of growing. Senior interviewers probe for this specifically because over-engineered code is a genuinely common real-world problem that's more expensive than under-engineered code in the long run — it adds indirection, makes the actual logic harder to trace through multiple wrapper layers, and adds files and abstractions future engineers have to learn before they can make a one-line change. A strong answer to "should I use Strategy here?" sometimes is "no — there are two stable cases here forever, an if/else is more readable and Strategy would just be ceremony."

### How do you decide whether a problem actually needs a named pattern?

Ask whether the *forces* the pattern was designed to manage are actually present: is the type/algorithm set expected to grow (favors Factory Method or Strategy over a switch statement), does the object genuinely have many optional configuration combinations (favors Builder over a long constructor), is there a real need to swap behavior at runtime or test variants in isolation (favors Strategy), does more than one unrelated part of the code need to react to one thing changing (favors Observer). If none of those forces exist yet, the straightforward, un-patterned code is usually the right call — patterns are insurance against a specific kind of future complexity, and insurance you pay for before you need it is still a cost. The interview-ready framing: "I'd start with the simplest thing that works, and refactor toward a named pattern once the forces that pattern manages actually show up in the code — not before."

<div class="verdict"><strong>The honest take:</strong> The strongest design-patterns answer in 2026 interviews isn't "here's the textbook definition" — it's "here's the problem this solves, here's when I'd actually reach for it, and here's when I wouldn't." Interviewers have all read the same Gang of Four definitions you have; they're listening for judgment, not recall.</div>

## How candidates actually practice this — and where it falls short

Most candidates prepare for design pattern interviews by reading the Gang of Four book or a summary site, memorizing UML diagrams, and maybe copying a sample implementation of each pattern into a personal notes doc. This builds recognition, but recognition isn't the actual interview skill — the skill is mapping a *novel, messy* problem description onto the right pattern live, explaining the tradeoff, and writing a clean implementation while someone watches.

**Reading refactoring.guru or the GoF book** gets you accurate definitions and clean canonical examples — genuinely good sources, and naming them in an interview shows you've gone past secondhand listicles. The gap: canonical examples are deliberately built to illustrate one pattern clearly, while real interview prompts are deliberately *messier* — "design a notification system that can alert by email, SMS, or push, and the list of channels will probably grow" doesn't say "use Observer and Strategy" out loud, you have to recognize it.

**LeetCode-style pattern quizzes** test recognition speed on clean multiple-choice descriptions, which is a different skill from being handed an ambiguous prompt and asked to talk through which pattern (if any) fits, write the code, and defend the choice when the interviewer pushes back with "what if I also need to support batching these notifications?"

**A friend's interview-questions PDF or a generic question bank** gets you the question list without the live coding and live follow-up pressure — and design pattern interviews are almost always live-coding-adjacent, not purely verbal, which most prep methods undersell.

[Greenroom](/) runs spoken mock interviews that include live pattern-design exercises — describing a messy, realistic system and being asked which pattern fits and why, with the same kind of pushback follow-up a real interviewer gives. It pairs well with practicing actual implementation speed and clarity in a [coding interview](/blog/common-coding-interview-mistakes) context, and with [explaining your reasoning clearly under follow-ups](/blog/coding-interview-communication-tips) — the skill that separates "knows the definition" from "can apply it live," which is exactly the gap between reading a textbook and passing a real interview.

## Practise applying patterns, not just naming them

You can recite all 23 Gang of Four pattern names and still freeze when an interviewer describes a real, slightly messy system and asks "what would you reach for here, and why?" That specific skill — mapping an unfamiliar problem onto a known shape, in real time, while explaining your reasoning to someone who's going to ask "but what if requirements X changed?" — is what separates candidates who memorized from candidates who understand. Greenroom runs spoken mock interviews with live pattern-recognition and system-design exercises, and gives feedback on whether your explanation actually held together, not just whether you named the right pattern. Pair it with our [object-oriented programming questions guide](/blog/oops-interview-questions) for the foundational concepts patterns build on, and [system design interviews: what they test](/blog/system-design-interviews-what-they-test) for the larger-scale version of the same judgment.

## Frequently asked questions

### What design patterns should I actually study for interviews in 2026?

Focus on the recurring core: Singleton, Factory Method, Builder, Observer, Strategy, Decorator, Adapter, and Dependency Injection. Know what problem each solves, when each is the wrong choice, and be able to write a clean, real implementation of each from scratch. The remaining Gang of Four patterns (Command, Visitor, Flyweight, Mediator, Chain of Responsibility) are worth a one-sentence mental model unless the role specifically touches a domain where they're common.

### Do design pattern interviews require memorizing UML diagrams?

No — interviewers care whether you can recognize the problem shape and write working code, not whether you can draw the exact UML class diagram from the Gang of Four book. Some interviewers ask you to sketch a rough class relationship to check your understanding, but a clean, correct code implementation matters far more than diagram notation.

### What's the most common mistake candidates make in design pattern interviews?

Reciting a textbook definition without being able to name a real or realistic use case, and reflexively applying a named pattern to a problem that doesn't actually have the complexity the pattern exists to manage. The second mistake is just as costly as the first — interviewers specifically probe for over-engineering by asking follow-ups like "would you really need that here?"

### How is a design patterns interview different from a general coding interview?

A general coding interview tests whether you can solve an algorithmic problem correctly and efficiently. A design patterns interview tests structural and architectural judgment — recognizing recurring problem shapes, choosing the right level of abstraction, and explaining tradeoffs between a pattern-based solution and a simpler one. The two often blend in practice: a coding interview for a senior role frequently includes "now refactor this to be more extensible," which is really a design-patterns question wearing a coding-interview costume.

### Are design patterns still relevant given how much modern frameworks abstract away?

Yes, just less visibly — React's hooks and context are Observer in different clothing, middleware chains in Express are Decorator, and most dependency-injection frameworks (Spring, NestJS, Angular's DI) are an entire ecosystem built around one pattern. The patterns didn't go away; the frameworks just implemented them for you, which is exactly why recognizing the underlying pattern in framework code is itself a strong interview signal — it shows you understand what the framework is actually doing, not just which methods to call.

### What's a good way to build real (not memorized) familiarity with patterns before an interview?

Go back through a real project you've built — your own, a class assignment, anything with actual code — and look for places where you already, unknowingly, implemented a pattern: an `if/else` chain picking between behaviors that's really crying out to be Strategy, a class doing too many unrelated things that's a Single Responsibility violation, a notification or event-handling bit of code that's really Observer. Naming the pattern in code you already wrote and understand builds far more durable, interview-ready familiarity than memorizing a fresh example from a tutorial, because you already know the problem's real edge cases and can speak to them when an interviewer pushes.

### How do I practice explaining design pattern tradeoffs out loud, not just writing the code?

Take a messy, realistic system description (a notification system, a payment integration, an undo feature) and practice talking through which pattern fits, why, and what you'd lose by choosing a simpler approach instead — out loud, ideally to another person or a structured mock interview that pushes back with follow-ups like a real interviewer would. Writing the code silently and reading model answers builds recognition; explaining the choice under follow-up questions builds the actual interview skill.

Design pattern interviews test judgment — recognizing the right problem shape and knowing when *not* to reach for a pattern — not memorized definitions. Greenroom runs spoken mock interviews with live pattern-recognition exercises and feedback on every answer. Free to start.
