Bird
Raised Fist0
Interview Prepoop-design-patternsmediumAmazonGoogleMicrosoftFlipkartRazorpayZepto

Adapter vs Facade vs Proxy - Structural Pattern Comparison

Choose your preparation mode3 modes available
▶
Steps
setup

Create PaymentGateway instance

We instantiate the PaymentGateway class which provides the make_payment method to process payments.

💡 This class represents the existing interface that clients want to use but may not be compatible with their expected interface.
Line:gateway = PaymentGateway()
💡 Understanding the original class's interface is essential before adapting or wrapping it.
📊
Adapter vs Facade vs Proxy - Structural Pattern Comparison - Watch the Algorithm Execute, Step by Step
Watching each pattern's mechanism unfold visually helps you grasp their distinct roles and how they simplify or control interactions in complex systems.
Step 1/10
·Active fill★Answer cell
Setup of the adaptee class which the Adapter will wrap.
PaymentGateway
+make_payment(amount)()
Adapter pattern composition: Adapter holds a reference to adaptee.
PaymentGateway
+make_payment(amount)()
PaymentAdapter
−gateway: PaymentGateway
+pay(amount)()
PaymentAdapter ◆ PaymentGateway
Adapter delegates method call to adaptee with interface translation.
PaymentGateway
+make_payment(amount)()
PaymentAdapter
−gateway: PaymentGateway
+pay(amount)()
PaymentAdapter ◆ PaymentGateway
Subsystem classes with distinct responsibilities.
LightingSystem
+turn_on()()
+turn_off()()
SecuritySystem
+arm()()
+disarm()()
Facade pattern composition: Facade aggregates subsystems.
LightingSystem
+turn_on()()
+turn_off()()
SecuritySystem
+arm()()
+disarm()()
HomeFacade
−lighting: LightingSystem
−security: SecuritySystem
+leave_home()()
+arrive_home()()
HomeFacade ◆ LightingSystemHomeFacade ◆ SecuritySystem
Facade method triggers multiple subsystem operations.
LightingSystem
+turn_off()()
SecuritySystem
+arm()()
HomeFacade
−lighting: LightingSystem
−security: SecuritySystem
+leave_home()()
HomeFacade ◆ LightingSystemHomeFacade ◆ SecuritySystem
Real subject class for Proxy pattern.
Database
+query()()
Proxy pattern composition: Proxy holds reference to real subject and adds control.
Database
+query()()
DatabaseProxy
−db: Database
−authenticated: bool
+authenticate(user)()
+query()()
DatabaseProxy ◆ Database
Proxy updates internal state to allow access.
DatabaseProxy
−authenticated: bool
+authenticate(user)()
Proxy forwards method call to real subject after access check.
DatabaseProxy
−authenticated: bool
+query()()
Database
+query()()
DatabaseProxy ◆ Database

Key Takeaways

✓ Adapter pattern changes the interface of an existing class to make it compatible with clients.

This insight is hard to see from code alone because the adapter's role is subtle and involves delegation with interface translation.

✓ Facade pattern simplifies complex subsystem interactions by providing a unified interface.

Seeing the facade coordinate multiple subsystem calls visually clarifies how it reduces client complexity.

✓ Proxy pattern controls access to a real subject by adding authentication or other checks before forwarding requests.

The proxy's control logic is often invisible in code but becomes clear when watching the access decision and delegation steps.

Practice

(1/5)
1. In the object-oriented design of a Snake and Ladder game, which component is primarily responsible for managing the state transitions of a player's position after a dice roll?
easy
A. The Dice class, since it generates the number that determines movement
B. The Player class, as it holds the current position and updates it directly
C. The Board class, because it contains the snakes and ladders and applies their effects
D. The GameController class, which orchestrates the game flow and updates player positions accordingly

Solution

  1. Step 1: Understand the role of Dice

    The Dice only generates a random number; it does not manage state transitions.
  2. Step 2: Consider Player class responsibilities

    Player holds position but should not decide how to update it considering snakes or ladders.
  3. Step 3: Analyze Board class role

    Board knows snakes and ladders but does not manage player state transitions directly.
  4. Step 4: Role of GameController

    GameController coordinates dice roll, queries Board for snakes/ladders, and updates Player position accordingly.
  5. Final Answer:

    Option D -> Option D
  6. Quick Check:

    GameController centralizes state transitions, ensuring separation of concerns.
Hint: GameController orchestrates state changes, not Dice or Player alone [OK]
Common Mistakes:
  • Thinking Dice manages player position
  • Assuming Player updates position without Board's input
  • Believing Board directly changes player state
2. You need to create different types of vehicles (cars, bikes) that share a common interface, and sometimes you want to create entire families of related vehicles (e.g., electric car + electric bike) ensuring consistency. Which design pattern best fits this requirement?
easy
A. Builder Pattern, because it constructs complex objects step-by-step.
B. Abstract Factory Pattern, because it creates families of related objects ensuring consistency.
C. Factory Pattern, because it creates simple objects based on a type parameter.
D. Singleton Pattern, because it ensures only one instance of each vehicle type.

Solution

  1. Step 1: Understand the requirement for families of related objects

    The problem states the need to create related vehicles (e.g., electric car and electric bike) that belong to a family and must be consistent.
  2. Step 2: Match pattern to requirement

    Abstract Factory is designed to create families of related objects, ensuring that the created objects are compatible and consistent.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Abstract Factory creates related object families, Factory creates single objects [OK]
Hint: Families of related objects -> Abstract Factory [OK]
Common Mistakes:
  • Confusing Factory with Abstract Factory
  • Using Builder for simple object creation
3. 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
4. What is a common trade-off or limitation when strictly enforcing the Liskov Substitution Principle in a large inheritance hierarchy?
medium
A. It can lead to overly rigid designs that prevent useful specialization.
B. It always improves code flexibility and reduces bugs without downsides.
C. It allows subclasses to freely change method signatures for optimization.
D. It eliminates the need for interface segregation.

Solution

  1. Step 1: Understand strict LSP enforcement

    Strict LSP means subclasses cannot alter behavior or method contracts in incompatible ways.
  2. Step 2: Analyze trade-offs

    This can restrict subclass implementations, making designs rigid and limiting specialization.
  3. Step 3: Evaluate options

    It can lead to overly rigid designs that prevent useful specialization. correctly identifies rigidity as a trade-off. It always improves code flexibility and reduces bugs without downsides. is false; strict LSP can reduce flexibility. It allows subclasses to freely change method signatures for optimization. is incorrect; method signatures must respect variance rules. It eliminates the need for interface segregation. is false; interface segregation addresses different concerns.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Strict LSP can constrain subclass design choices.
Hint: Strict LSP enforces substitutability but can limit subclass flexibility.
Common Mistakes:
  • Believing strict LSP has no downsides
  • Confusing LSP with interface segregation
  • Assuming method signatures can be freely changed
5. Consider the following buggy code snippet from a thread-safe observer pattern implementation. Which line contains the subtle bug that can cause unsubscribed observers to still receive notifications?
def unsubscribe(self, observer, event_type):
    with self.lock:
        if event_type in self.observers:
            self.observers[event_type].remove(observer)
            if not self.observers[event_type]:
                del self.observers[event_type]
Assume that observer may not be subscribed to event_type when unsubscribe is called.
medium
A. Line 5: No handling of empty observer dictionary
B. Line 2: Lock is not acquired properly
C. Line 3: Missing check if observer is in the set before remove()
D. Line 4: Deleting event_type key prematurely

Solution

  1. Step 1: Analyze unsubscribe logic

    Line 3 calls remove() on the set without checking if observer exists, which raises KeyError if observer not subscribed.
  2. Step 2: Identify fix

    Check if observer in self.observers[event_type] before remove() to avoid errors and ensure proper removal.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    remove() without membership check causes runtime error [OK]
Hint: remove() without membership check can raise error [OK]
Common Mistakes:
  • Assuming remove() silently ignores missing elements
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