← All articles
12 min read

Design Patterns Interview Questions: OOP and SOLID (2026)

Interviewers rarely ask you to recite the Gang of Four catalog. They hand you messy code and watch which pattern you reach for. This guide maps the 10 most-asked patterns to the problems they solve, with before/after refactors.

Design patterns interview questions test whether you can recognize a recurring design problem in code and apply a proven structure to fix it, explaining the trade-offs as you go. In 2026 most interviewers skip pure definitions and instead show you flawed code or a low-level design prompt, then judge which pattern you reach for and why. The fastest way to prepare is to learn patterns by the problem they solve, not by their category.

Key Takeaways

  • Interviewers test pattern selection, not memorization. Know which code smell each pattern fixes and when it is overkill.
  • Ten patterns cover most questions: Singleton, Factory Method, Builder, Adapter, Decorator, Facade, Strategy, Observer, State, and Command.
  • SOLID answers land best as "principle, violation, fix" in about 30 seconds each.
  • Composition over inheritance is the idea underneath Strategy, Decorator, and State. Expect a follow-up on it.
  • Singleton is the most-asked pattern and the most-criticized. Be ready to argue both sides and offer dependency injection as the alternative.
  • Patterns appear mostly inside low-level design rounds such as parking lots, elevators, and vending machines.

What Do Design Pattern Interviews Actually Test?

A design pattern is a named, reusable solution to a problem that keeps recurring in object-oriented code. The term was popularized by the 1994 book Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides, known as the Gang of Four (GoF). It catalogs 23 patterns split into creational, structural, and behavioral groups.

Interviews use patterns in three ways:

  1. Concept questions. "What is the Observer pattern?" or "Factory vs Strategy?" These show up in phone screens, especially for Java or C# roles.
  2. Refactoring prompts. You get a class with a giant switch statement and are asked to make it extensible.
  3. Low-level design rounds. You design classes for a parking lot or ride-matching service, and patterns are how you justify your structure. Our parking lot low-level design walkthrough shows this format end to end.

In every format, the signal is the same: can you write code that is easy to change without breaking? That overlaps heavily with what interviewers look for in coding interviews generally, such as clarity, trade-off awareness, and communication.

OOP Pillars Refresher

Object-oriented programming is a paradigm that organizes code around objects that bundle state with the behavior that operates on it. Every pattern builds on the four pillars, so expect at least one warm-up question here.

PillarOne-line definitionWhat interviewers want to hear
EncapsulationHide internal state behind a controlled interfaceInvariants are protected; callers cannot put the object in an invalid state
AbstractionExpose what an object does, not howCallers depend on interfaces, so implementations can change
InheritanceA subclass reuses and extends a parent typeUseful for true "is-a" relationships, but creates tight coupling
PolymorphismOne interface, many implementations, resolved at runtimeReplaces type-checking conditionals with method dispatch

The follow-up is almost always "composition vs inheritance." Composition means an object holds other objects and delegates to them. The GoF book's advice to "favor object composition over class inheritance" is the reason most behavioral patterns pass objects around instead of subclassing.

Language details matter too. Python has no interface keyword and relies on abc.ABC or duck typing, while Java and C# have explicit interfaces. If you are interviewing in one language, review its specifics in our Java interview questions or Python interview questions guides.

SOLID Principles With Examples

SOLID is a set of five object-oriented design principles collected by Robert C. Martin in the early 2000s, with the acronym itself coined by Michael Feathers. Use the "principle, violation, fix" format for each.

S: Single Responsibility Principle. A class should have one reason to change. A ReportService that queries the database, formats a PDF, and emails it has three reasons. Split it into a repository, a formatter, and a notifier.

O: Open/Closed Principle. Code should be open for extension but closed for modification. If adding a new payment method means editing an if/elif chain in checkout(), you violate it. Introduce a PaymentMethod interface so new methods are new classes.

L: Liskov Substitution Principle. Subtypes must be usable anywhere their parent type is expected without breaking correctness. The classic violation is Square extending Rectangle: setting the width on a square silently changes its height, so code that assumes independent sides breaks.

I: Interface Segregation Principle. Clients should not depend on methods they do not use. A Worker interface with work() and eat() forces a Robot to stub out eat(). Split it into Workable and Feedable.

D: Dependency Inversion Principle. High-level modules should depend on abstractions, not concrete low-level classes. Here is the shortest refactor you can show on a whiteboard:

# Before: OrderService is welded to MySQL
class OrderService:
    def __init__(self):
        self.repo = MySQLOrderRepo()

# After: depend on an abstraction, inject the concrete class
from abc import ABC, abstractmethod

class OrderRepo(ABC):
    @abstractmethod
    def save(self, order): ...

class OrderService:
    def __init__(self, repo: OrderRepo):
        self.repo = repo

Dependency Inversion is the principle people confuse most. It is not the same as dependency injection. Inversion is the design rule (depend on abstractions); injection is one technique for supplying the concrete object.

The Pattern-to-Problem Table

Matching a code smell to a pattern is the skill most interview prep material skips. Use this table as your lookup during practice: read the smell, name the pattern, then sketch the refactor.

Code smell or symptomPatternCategoryWhat it costs you
Many places need one shared resource (config, connection pool) and duplicates cause bugsSingletonCreationalHidden global state, harder testing
if type == "x": X() scattered across the codebaseFactory MethodCreationalOne more class per product family
Constructor with 8+ parameters, many optionalBuilderCreationalExtra builder class, more lines
Third-party class has the wrong interface for your codeAdapterStructuralA thin wrapper to maintain
Subclass explosion like LoggedCachedRetryingClientDecoratorStructuralMany small wrapper objects, harder debugging
Callers juggle five subsystems to do one taskFacadeStructuralFacade can grow into a god object
Growing if/elif on algorithm choice (pricing, routing, sorting)StrategyBehavioralMore classes, caller must pick one
Objects poll another object or hardcode who to notifyObserverBehavioralEvent ordering and memory leaks from dangling listeners
Methods full of if self.status == ... checksStateBehavioralOne class per state
Need undo, queueing, retry, or logging of actionsCommandBehavioralEvery action becomes an object

The last column is what separates strong answers. Interviewers often ask "when would you not use this?" and a candidate who names the cost first sounds like someone who has maintained real code.

Creational Patterns: Singleton, Factory, Builder

Creational patterns control how objects are created so callers do not depend on concrete classes or messy construction logic.

Singleton

Singleton ensures a class has exactly one instance and provides a global access point to it. It is the most-asked pattern, usually with a twist: make it thread-safe, or explain why it is criticized.

import threading

class Config:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
        return cls._instance

That is double-checked locking. In Java, the cleanest answers are an enum singleton or the holder-class idiom, and if you use double-checked locking the field must be volatile. For more on the threading side, see our concurrency and multithreading interview questions.

The criticism to raise yourself: Singleton hides dependencies and makes tests share state. The modern alternative is to create one instance at startup and inject it.

Factory Method

Factory Method moves the decision of which concrete class to build into one place.

# Before: this branch is copied into three files
if kind == "email":
    n = EmailNotifier()
elif kind == "sms":
    n = SmsNotifier()

# After: one place to change
NOTIFIERS = {"email": EmailNotifier, "sms": SmsNotifier}

def make_notifier(kind: str) -> Notifier:
    return NOTIFIERS[kind]()

A strict GoF Factory Method uses a subclass to override a creation method. The registry version above is a "simple factory." It is fine to say so; interviewers appreciate the precision.

Builder

Builder constructs a complex object step by step, which fixes telescoping constructors.

# Before
req = HttpRequest("GET", url, None, None, 30, True, 3, None)

# After
req = (HttpRequest.builder("GET", url)
       .timeout(30)
       .retries(3)
       .build())

In Python, keyword arguments with defaults or a dataclass often remove the need for Builder entirely. Saying that shows judgment rather than pattern worship.

Pattern questions often arrive as live refactoring: you see 60 lines of tangled code and have minutes to name the right fix. TechScreen is an invisible AI assistant that suggests the matching pattern and a clean refactor in real time during Zoom, Teams, and CoderPad rounds, without showing up on screen share. Try it with 3 free tokens, no credit card.

Get started free →

Structural Patterns: Adapter, Decorator, Facade

Structural patterns describe how classes and objects are combined into larger structures while keeping them flexible.

Adapter

Adapter converts one interface into another that the client expects.

class LegacyPayments:
    def make_payment(self, cents, curr): ...

class PaymentGateway(ABC):
    @abstractmethod
    def charge(self, amount: Decimal): ...

class LegacyAdapter(PaymentGateway):
    def __init__(self, legacy: LegacyPayments):
        self.legacy = legacy

    def charge(self, amount):
        self.legacy.make_payment(int(amount * 100), "USD")

The common follow-up: Adapter changes an interface, while Facade simplifies one, and Decorator keeps the same interface but adds behavior.

Decorator

Decorator wraps an object to add responsibilities without subclassing. It fixes class explosion.

# Before: CachedClient, LoggedClient, CachedLoggedClient, ...

# After: stack wrappers that share one interface
client = LoggingClient(CachingClient(HttpClient()))

Do not confuse this with Python's @decorator syntax. Python decorators wrap functions; the GoF Decorator wraps objects. They share the idea, not the mechanics. Java's BufferedReader(new FileReader(...)) is the textbook real-world example.

Facade

Facade gives a simple entry point to a complex subsystem. A checkout() method that coordinates inventory, payment, and shipping services so the controller makes one call is a facade. Warn that a facade can turn into a god object if every new feature gets bolted onto it.

Other structural patterns you may be asked to define, though rarely to implement, are Proxy (controls access, such as lazy loading or caching), Composite (treats trees of objects uniformly, such as a file system), and Bridge.

Behavioral Patterns: Strategy, Observer, State, Command

Behavioral patterns describe how objects divide responsibility and communicate.

Strategy

Strategy defines a family of interchangeable algorithms behind one interface. It is the textbook fix for an Open/Closed violation.

# Before
def price(order, tier):
    if tier == "gold":
        return order.total * 0.8
    elif tier == "silver":
        return order.total * 0.9
    return order.total

# After
class Pricing(ABC):
    @abstractmethod
    def apply(self, total: float) -> float: ...

class Gold(Pricing):
    def apply(self, total): return total * 0.8

def price(order, pricing: Pricing):
    return pricing.apply(order.total)

Factory vs Strategy

This is one of the most-asked comparison questions. Factory decides which object to create. Strategy decides which algorithm to run, through an object you already have. They pair naturally: a factory reads the customer tier and returns the right Pricing strategy.

Observer

Observer lets one subject notify many subscribers when its state changes, without knowing who they are.

class OrderEvents:
    def __init__(self):
        self._subs = []

    def subscribe(self, fn):
        self._subs.append(fn)

    def publish(self, order):
        for fn in self._subs:
            fn(order)

Mention the risks: listeners that are never unsubscribed leak memory, and ordering between subscribers is usually undefined. At system scale, Observer becomes pub/sub through a message broker, which connects to topics in our system design interview guide.

State

State moves state-specific behavior into separate classes, so an object changes behavior when its internal state changes. It fixes methods packed with if self.status == "PAID" checks. A vending machine or order lifecycle is the standard example: Pending, Paid, and Shipped each implement cancel() differently.

State and Strategy look identical in a class diagram. The difference is intent: with State, the object switches its own state as events happen; with Strategy, the client picks the algorithm.

Command

Command turns a request into an object. That object can be queued, logged, retried, or undone.

class Command(ABC):
    @abstractmethod
    def execute(self): ...
    @abstractmethod
    def undo(self): ...

history = []

def run(cmd: Command):
    cmd.execute()
    history.append(cmd)

Text editors, job queues, and transactional migrations are the usual examples. Template Method, Iterator, and Chain of Responsibility (middleware pipelines) round out the behavioral patterns worth knowing by definition.

Common Design Patterns Interview Questions

These are the questions that come up again and again, with the angle a strong answer takes.

  1. What is a design pattern, and why use one? A reusable solution to a recurring design problem. It gives the team shared vocabulary and a tested structure. Add that patterns are tools, not goals.
  2. Implement a thread-safe Singleton. Show double-checked locking or a language idiom, then volunteer the testing downside.
  3. Factory vs Abstract Factory? Factory Method creates one product. Abstract Factory creates families of related products, such as a DarkThemeFactory that returns matching buttons and menus.
  4. Factory vs Strategy? Creation vs behavior, as covered above.
  5. Decorator vs inheritance? Decorator composes behavior at runtime and avoids combinatorial subclasses.
  6. Adapter vs Facade vs Proxy? Adapter changes the interface, Facade simplifies it, Proxy keeps it and controls access.
  7. State vs Strategy? Same structure, different intent and who triggers the switch.
  8. Which patterns does your framework use? Spring beans default to singleton scope, Java I/O streams use Decorator, and React's context and many event systems resemble Observer. Grounding answers in tools you use builds credibility.
  9. Refactor this switch statement. Identify the axis of change, extract an interface, and move each branch into a class (Strategy or State).
  10. Design a parking lot, elevator, or vending machine. Use Factory for vehicle or spot creation, Strategy for pricing or dispatch, State for the machine lifecycle, and Observer for display boards.
  11. When is a pattern overkill? When there is only one implementation and no realistic second one. YAGNI applies.
  12. Explain each SOLID principle with an example. Use the violation-and-fix format from earlier.

When you get a refactoring prompt, narrate before you type: name the smell, name the pattern, state the cost. Our guide on how to think out loud in a coding interview covers that habit in depth.

How to Prepare in One Week

A focused week is enough if you already write object-oriented code daily.

DayFocusOutput
1OOP pillars, composition vs inheritanceOne-sentence answers you can say aloud
2SOLIDA violation-and-fix example for each principle
3Singleton, Factory, BuilderCode each from memory, including thread-safe Singleton
4Adapter, Decorator, FacadeCode each, plus a comparison of all three
5Strategy, Observer, State, CommandRefactor one switch statement into Strategy and one into State
6Low-level design mockParking lot or vending machine in 45 minutes
7Review the pattern-to-problem tableExplain any row in under a minute

Backend and enterprise roles lean on this material hardest; see the backend engineer interview guide for how it fits alongside API and database questions. For senior and staff loops, expect deeper trade-off discussion and less code, as described in our staff engineer interview guide.

Recall is the hard part under pressure: you know Decorator cold until an interviewer asks you to contrast it with Proxy in the middle of a design round. TechScreen listens to the question and shows a concise answer and code sketch on a screen only you can see, invisible to screen sharing on Zoom, Google Meet, and Teams. Start with 3 free tokens and try it on your next mock.

Get started free →

Frequently Asked Questions

Which design patterns are most commonly asked in interviews?

The patterns that come up most often are Singleton, Factory Method, Builder, Adapter, Decorator, Facade, Strategy, Observer, State, and Command. Abstract Factory, Proxy, Composite, and Template Method appear less often but show up in low-level design rounds. Interviewers usually care less about naming the pattern and more about whether you can explain which problem it solves and what it costs in added complexity.

What is the difference between the Factory and Strategy patterns?

Factory is a creational pattern: it decides which class to instantiate so callers do not depend on concrete types. Strategy is a behavioral pattern: it swaps one algorithm for another behind a shared interface at runtime. They often work together. A factory can read configuration and return the right strategy object, and the caller then uses that strategy without knowing which one it got. One answers 'what do I build', the other answers 'how do I do this task'.

Why is Singleton considered an anti-pattern by some engineers?

Singleton introduces hidden global state. Any class can reach the instance without declaring it as a dependency, which makes code harder to test because you cannot easily swap in a fake. It also couples lifetime and access control into one class and needs care in multithreaded code. Most teams now prefer creating a single instance at the composition root and passing it in through dependency injection, which keeps the one-instance guarantee without the global access.

How do I explain SOLID principles in an interview?

Give each principle in one sentence, then attach a concrete violation and fix. For example, Single Responsibility: a class that both calculates invoices and emails them has two reasons to change, so split it. Open/Closed: replace a growing if/else on payment type with a strategy interface. Interviewers remember examples, not definitions. Keep it to about 30 seconds per principle unless they ask you to go deeper.

Do FAANG companies ask design pattern questions?

Rarely as standalone trivia. Patterns show up inside low-level design or object-oriented design rounds, such as designing a parking lot, an elevator system, or a vending machine. Companies with object-oriented stacks, including many enterprise and fintech employers, are more likely to include them. You are judged on whether your class design is extensible and testable, and patterns are the vocabulary you use to explain it.

What is the difference between composition and inheritance?

Inheritance creates an 'is-a' relationship where a subclass reuses and extends a parent's behavior, fixed at compile time. Composition creates a 'has-a' relationship where an object holds references to other objects and delegates work to them, which can change at runtime. Most design patterns, including Strategy, Decorator, and State, rely on composition because it avoids deep class hierarchies and keeps behavior swappable. 'Favor composition over inheritance' comes from the Gang of Four book.

How many design patterns should I learn for interviews?

Ten to twelve is enough for most interviews. The original Gang of Four book describes 23 patterns, but several, such as Flyweight, Interpreter, Memento, and Visitor, are rarely asked outside specialized roles. Depth beats breadth: you should be able to sketch each common pattern in code, name the smell it fixes, and explain when it would be overkill.

Ready to use AI assistance in your next interview?

TechScreen is the invisible AI assistant trusted by engineers interviewing at Google, Meta, Amazon, and hundreds of other companies. Start with 3 free tokens — no credit card required.

Ace your next interview →