Bird
Raised Fist0
Interview Prepoop-design-patternsmediumAmazonGoogleMicrosoftFlipkartRazorpayZepto

Adapter vs Facade vs Proxy - Structural Pattern Comparison

Choose your preparation mode3 modes available
🎯
Adapter vs Facade vs Proxy - Structural Pattern Comparison
mediumOOPAmazonGoogleMicrosoft

Imagine you have a legacy payment system that speaks a different language than your new app, a complex home automation system you want to simplify for users, and a security guard controlling access to a sensitive resource. How do you design these interactions cleanly?

💡 Beginners often confuse these patterns because they all deal with object composition and interfaces, but their intents and use cases differ significantly. Adapter focuses on making incompatible interfaces work together, Facade simplifies complex systems by providing a unified interface, and Proxy controls access or adds responsibilities without changing the original object. Understanding these distinctions helps avoid mixing their responsibilities.
📋
Interview Question

Explain the differences and purposes of the Adapter, Facade, and Proxy design patterns. When and why would you use each? Compare their roles in structural design patterns.

Intent and purpose of Adapter, Facade, and Proxy patternsHow each pattern changes or controls access to underlying componentsUse cases and trade-offs for each pattern
💡
Scenario & Trace
ScenarioIntegrating a new payment gateway with an existing e-commerce platform that expects a different interface
The Adapter wraps the new payment gateway's interface and translates calls into the format expected by the platform, enabling compatibility without changing existing code.
ScenarioProviding a simplified interface to a complex home automation system with many subsystems like lighting, HVAC, and security
The Facade exposes a single unified interface that internally coordinates calls to multiple subsystems, hiding complexity from the client.
ScenarioControlling access to a sensitive database by adding authentication and caching layers without changing the database code
The Proxy acts as a surrogate that intercepts client requests, performs access control and caching, then forwards requests to the real database object.
  • What if the Adapter needs to support multiple incompatible interfaces simultaneously?
  • How does the Facade pattern handle subsystem changes or extensions without breaking clients?
  • What happens if the Proxy introduces latency or failure points in critical resource access?
⚠️
Common Mistakes
Confusing Adapter with Facade as both simplify interfaces

Interviewer doubts your grasp of pattern intent and design goals

✅ Remember Adapter changes interface to make incompatible interfaces work together; Facade simplifies a complex subsystem with a unified interface.

Thinking Proxy always adds security or caching

Interviewer sees a narrow understanding of Proxy's broader role

✅ Understand Proxy can add various responsibilities like lazy loading, logging, or remote access control, not just security.

Assuming Facade changes subsystem interfaces

Interviewer questions your understanding of subsystem encapsulation

✅ Facades do not alter subsystem interfaces; they provide a new simplified interface on top.

Believing Adapter and Proxy both wrap incompatible interfaces

Interviewer suspects confusion between compatibility and access control

✅ Adapter wraps to translate interfaces; Proxy wraps to control or enhance access to the same interface.

🧠
Basic Definition - What It Is
💡 This level covers the essential purpose and difference of each pattern in simple terms, helping beginners grasp their core intent and avoid confusion.

Intuition

Adapter makes incompatible interfaces compatible, Facade simplifies complex systems, Proxy controls access to an object.

Explanation

The Adapter pattern allows two incompatible interfaces to work together by wrapping one interface with another. The Facade pattern provides a simplified interface to a complex subsystem, hiding its internal complexity. The Proxy pattern acts as a placeholder or surrogate for another object to control access, add functionality like lazy loading or security, without changing the original object's code.

Memory Hook

💡 Adapter = Translator, Facade = Simplifier, Proxy = Gatekeeper

Illustrative Code

class OldPaymentSystem:
    def pay(self, amount):
        print(f"Paying {amount} using old system")

class NewPaymentGateway:
    def make_payment(self, value):
        print(f"Making payment of {value} via new gateway")

class PaymentAdapter:
    def __init__(self, new_gateway):
        self.new_gateway = new_gateway

    def pay(self, amount):
        # Translate pay to make_payment
        self.new_gateway.make_payment(amount)

# Usage
old_system = OldPaymentSystem()
new_gateway = NewPaymentGateway()
adapter = PaymentAdapter(new_gateway)
adapter.pay(100)

Interview Questions

❓ What is the main intent of the Adapter pattern?
  • To convert one interface to another expected by the client
  • To enable compatibility between otherwise incompatible interfaces
❓ How does a Facade help clients?
  • By providing a simple unified interface
  • By hiding the complexity of multiple subsystems
⏱
Depth Level
Interview Time30 seconds
Depthbasic

This level focuses on conceptual understanding without code complexity. The Adapter pattern typically adds a constant overhead of method call translation, Facade simplifies client interaction without changing subsystem complexity, and Proxy adds control layers with minimal overhead.

Interview Target: Minimum floor - never go below this

Knowing only this helps pass initial rounds but lacks depth for on-site interviews.

🧠
Mechanism Depth - How It Works
💡 This level explains internal workings, interactions, and typical use cases expected in product company interviews, helping candidates demonstrate deeper understanding.

Intuition

Adapter wraps and translates interfaces, Facade delegates to multiple subsystems, Proxy intercepts and controls requests.

Explanation

The Adapter pattern involves creating a wrapper class that implements the target interface and holds an instance of the incompatible class. It translates client calls into calls understood by the wrapped object. The Facade pattern defines a higher-level interface that delegates client requests to appropriate subsystem classes, coordinating their interactions and hiding their complexity. The Proxy pattern implements the same interface as the real object and controls access by adding pre-processing (e.g., authentication), post-processing, caching, or lazy initialization before forwarding calls to the real object. Each pattern uses composition but with different intents: Adapter focuses on interface compatibility, Facade on simplifying usage, and Proxy on controlling access or adding responsibilities.

Memory Hook

💡 Adapter = Wrapper Translator, Facade = Unified Controller, Proxy = Access Controller

Illustrative Code

class PaymentGateway:
    def make_payment(self, amount):
        print(f"Processing payment of {amount}")

class PaymentAdapter:
    def __init__(self, gateway):
        self.gateway = gateway

    def pay(self, amount):
        # Translate pay to make_payment
        self.gateway.make_payment(amount)

class LightingSystem:
    def turn_on(self):
        print("Lights on")
    def turn_off(self):
        print("Lights off")

class SecuritySystem:
    def arm(self):
        print("Security armed")
    def disarm(self):
        print("Security disarmed")

class HomeFacade:
    def __init__(self, lighting, security):
        self.lighting = lighting
        self.security = security

    def leave_home(self):
        self.lighting.turn_off()
        self.security.arm()

    def arrive_home(self):
        self.security.disarm()
        self.lighting.turn_on()

class Database:
    def query(self):
        print("Querying database")

class DatabaseProxy:
    def __init__(self, db):
        self.db = db
        self.authenticated = False

    def authenticate(self, user):
        if user == "admin":
            self.authenticated = True
            print("User authenticated")
        else:
            print("Authentication failed")

    def query(self):
        if self.authenticated:
            print("Proxy: Access granted")
            self.db.query()
        else:
            print("Proxy: Access denied")

# Usage
# Adapter
gateway = PaymentGateway()
adapter = PaymentAdapter(gateway)
adapter.pay(200)

# Facade
lighting = LightingSystem()
security = SecuritySystem()
home = HomeFacade(lighting, security)
home.leave_home()
home.arrive_home()

# Proxy
db = Database()
proxy = DatabaseProxy(db)
proxy.query()
proxy.authenticate("admin")
proxy.query()

Interview Questions

❓ How does the Proxy pattern add functionality without changing the real object?
  • By implementing the same interface as the real object
  • By intercepting calls and adding behavior before/after forwarding
  • By controlling access, caching, or lazy loading
❓ What happens if the Facade needs to expose new subsystem features?
  • Facade interface may need extension
  • Clients remain decoupled from subsystem changes
  • Subsystems can evolve independently
❓ Can Adapter be used to support multiple incompatible interfaces?
  • Yes, by implementing multiple adapter classes or interfaces
  • Or by using multiple adapters chained or combined
⏱
Depth Level
Interview Time2-3 minutes
Depthintermediate

Adapter adds a constant time overhead for translating calls. Facade simplifies client interaction but underlying subsystem complexity remains unchanged. Proxy adds overhead for access control or caching, which can vary but typically is O(1) per call. Space overhead is minimal for all, mainly storing references to wrapped objects.

Interview Target: Target level for FAANG on-sites

Mastering this level distinguishes you from most candidates.

📊
Explanation Depth Levels
💡 Choose your depth based on interview stage and role expectations; deeper knowledge is required for senior or FAANG roles.
LevelInterview TimeSuitable ForRisk
Basic Definition30sScreening call or initial HR roundToo shallow for technical on-site interviews
Mechanism Depth2-3 minutesTechnical interviews at product companies and FAANGInsufficient if you cannot discuss trade-offs or edge cases
💼
Interview Strategy
💡 Use this guide to structure your explanation clearly and confidently before every mock or real interview.

How to Present

Start with a concise definition of each pattern and their intentGive a relatable real-world example or analogy for eachExplain the internal mechanism and how they differ in structure and purposeDiscuss edge cases or trade-offs to show deeper understanding

Time Allocation

Definition: 30s → Example: 1min → Mechanism: 2min → Edge cases: 30s. Total ~4min

What the Interviewer Tests

Your ability to distinguish similar patterns, explain their use cases, and reason about design trade-offs.

Common Follow-ups

  • How would you implement a Proxy that adds caching?
  • Can you combine Adapter and Facade in a system? How?
💡 These follow-ups test your practical understanding and ability to apply patterns in real scenarios.
🔍
Pattern Recognition

When to Use

Interviewers ask about these patterns when discussing system design, code refactoring, or when you mention structural design patterns.

Signature Phrases

'Explain the difference between Adapter, Facade, and Proxy''Compare Adapter and Proxy patterns''What happens when you need to integrate incompatible interfaces?'

NOT This Pattern When

Similar Problems

Practice

(1/5)
1. Imagine a class responsible for both data persistence and data validation. When a change in validation rules occurs, trace the impact on the class and explain what happens step-by-step.
easy
A. Only the validation methods need modification; persistence remains unaffected, so SRP is maintained.
B. Changing validation rules forces modifying the entire class, risking unintended side effects on persistence logic.
C. Validation changes automatically propagate to persistence without code changes due to tight coupling.
D. Persistence logic will break because validation and persistence are tightly integrated and inseparable.

Solution

  1. Step 1: Identify responsibilities

    The class handles both validation and persistence, two distinct reasons to change.
  2. Step 2: Trace change impact

    Changing validation rules requires modifying validation code inside the class.
  3. Step 3: Side effects

    Because persistence logic shares the class, changes risk affecting persistence unintentionally, increasing maintenance risk.
  4. Step 4: SRP violation

    This coupling violates SRP, as one reason to change (validation) affects unrelated functionality (persistence).
  5. Final Answer:

    Option B -> Option B
  6. Quick Check:

    One reason to change should not force changes in unrelated code -> SRP violation.
Hint: One reason to change means one place to modify.
Common Mistakes:
  • Assuming changes affect only related methods without side effects.
  • Believing tight coupling is harmless if code is in one class.
  • Thinking validation and persistence are always linked.
2. What is a key trade-off when using the Singleton pattern for managing the ParkingLot instance in a multi-level parking system?
medium
A. Singleton pattern automatically handles persistence of ParkingLot state across system restarts
B. Singleton ensures only one ParkingLot instance, which simplifies global access but limits scalability for multiple lots
C. Singleton improves concurrency by allowing multiple threads to create instances simultaneously
D. Singleton eliminates the need for synchronization in multi-threaded environments

Solution

  1. Step 1: Understand Singleton purpose

    Singleton restricts instantiation to one object, providing a global point of access.
  2. Step 2: Identify trade-offs

    While simplifying access, it limits flexibility and scalability, especially if multiple parking lots or levels need independent management.
  3. Step 3: Address misconceptions

    Singleton does not inherently improve concurrency or persistence, nor does it remove synchronization needs.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Singleton simplifies access but restricts scalability [OK]
Hint: Singleton = one instance, good for global access but bad for scalability [OK]
Common Mistakes:
  • Believing Singleton improves concurrency or persistence
  • Assuming Singleton removes synchronization requirements
3. Which of the following statements about using inheritance to model different vehicle types in the parking lot system is INCORRECT?
medium
A. Inheritance allows sharing common vehicle attributes and behaviors in a base Vehicle class
B. Using inheritance for vehicle types can lead to rigid designs that are hard to extend with new types
C. Inheritance is always the best approach to add new vehicle types without modifying existing code
D. Polymorphism enables treating all vehicle types uniformly when allocating parking spots

Solution

  1. Step 1: Review inheritance benefits

    Inheritance supports code reuse and polymorphism for uniform handling.
  2. Step 2: Recognize limitations

    Inheritance hierarchies can become rigid and hard to extend, violating open-closed principle.
  3. Step 3: Identify incorrect statement

    Claiming inheritance is always best ignores alternatives like composition or interfaces that improve extensibility.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Inheritance is not always best for extensibility [OK]
Hint: Inheritance can cause rigidity; prefer composition for extensibility [OK]
Common Mistakes:
  • Assuming inheritance is always the best design choice
  • Ignoring polymorphism benefits
4. What is a key trade-off or limitation when using multiple inheritance to solve the Diamond Problem in object-oriented design?
medium
A. Multiple inheritance always leads to ambiguous method calls that cannot be resolved.
B. Multiple inheritance eliminates the need for Method Resolution Order (MRO).
C. Multiple inheritance reduces code reuse compared to single inheritance.
D. Using multiple inheritance can increase complexity and make the class hierarchy harder to understand and maintain.

Solution

  1. Step 1: Understand the Diamond Problem

    Diamond Problem arises when a class inherits from two classes that share a common ancestor, causing ambiguity.
  2. Step 2: Evaluate Multiple inheritance always leads to ambiguous method calls that cannot be resolved.

    Multiple inheritance can cause ambiguity, but languages use MRO to resolve it, so it is not always unresolved.
  3. Step 3: Evaluate Multiple inheritance eliminates the need for Method Resolution Order (MRO).

    MRO is essential in multiple inheritance to resolve method calls, so multiple inheritance does not eliminate MRO.
  4. Step 4: Evaluate Multiple inheritance reduces code reuse compared to single inheritance.

    Multiple inheritance generally increases code reuse by combining features from multiple classes.
  5. Step 5: Correct trade-off

    Using multiple inheritance can increase complexity and make the class hierarchy harder to understand and maintain. correctly identifies that multiple inheritance increases complexity and can make hierarchies harder to maintain.
  6. Final Answer:

    Option D -> Option D
  7. Quick Check:

    Complexity and maintainability are key trade-offs in multiple inheritance.
Hint: Multiple inheritance = power with complexity cost
Common Mistakes:
  • Believing multiple inheritance always causes irresolvable ambiguity
  • Thinking MRO is unnecessary with multiple inheritance
  • Assuming multiple inheritance reduces code reuse
5. Which of the following statements about the Interface Segregation Principle (ISP) is INCORRECT?
medium
A. ISP aims to reduce the number of interfaces to simplify the system.
B. Clients should only depend on the interfaces that are relevant to them.
C. ISP encourages creating multiple specific interfaces rather than one general-purpose interface.
D. ISP helps avoid forcing clients to implement methods they do not use.

Solution

  1. Step 1: Recall ISP's core principle

    ISP promotes splitting interfaces so clients depend only on what they need, often increasing interface count.
  2. Step 2: Analyze options

    ISP aims to reduce the number of interfaces to simplify the system. incorrectly states ISP reduces the number of interfaces; in reality, it often increases them to avoid fat interfaces. Options A, B, and D correctly describe ISP goals.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    ISP is about interface granularity, not minimizing interface count.
Hint: ISP splits interfaces; it doesn't minimize their count.
Common Mistakes:
  • Confusing ISP with interface minimization
  • Assuming fewer interfaces always mean better design
  • Ignoring client-specific interface needs
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