Structural Patterns • Facade PatternHard⏱️ ~3 min
Facade Pattern - Interview Deep Dive
Common Interview Questions and Model Answers
Q1: Can clients still access subsystem classes directly?
Answer: Yes, and this is intentional. Facade does not encapsulate or hide the subsystem, it merely provides a convenient interface. If a client needs fine-grained control (for example, custom gate timing in parking lot), they can bypass the facade and use
GateController directly. However, most clients should prefer the facade for common operations. If you find many clients bypassing the facade, it indicates either the facade API is incomplete or the abstraction level is wrong.Q2: How do you handle errors in the facade when one subsystem fails?
Answer: The facade must implement compensating actions (rollback logic). For example, in
processEntry(), if gate opening fails after spot reservation, the facade must call spotManager.releaseSpot() before returning an error. Three approaches: First, try-catch blocks with explicit cleanup in catch. Second, transaction-like semantics where facade tracks actions and reverses them on failure. Third, return a Result object (not throwing exceptions) so client can decide how to proceed. The second approach is most robust for complex workflows.Q3: Should facade be a Singleton?
Answer: Not necessarily. While many facades are stateless and can be singletons (for example,
PaymentFacade), some need to maintain context (for example, SessionFacade for user session). Additionally, Singleton makes testing harder. Better approach: use Dependency Injection (DI) where framework manages facade lifecycle. If you must ensure single instance, let DI container handle it rather than hardcoding Singleton pattern into facade itself. This keeps facade testable with mock subsystems.Machine Coding Considerations
Class Design: Start by identifying subsystem classes first. Common mistake is designing facade before understanding subsystem boundaries. In a Library Management System, identify
BookRepository, UserRepository, FineCalculator, NotificationService first, then create LibraryFacade that coordinates them for operations like checkoutBook() and returnBook().Initialization: Decide whether facade creates subsystem objects (strong ownership) or receives them via constructor (dependency injection). DI is preferred for testing. However, if subsystems are internal implementation details not exposed elsewhere, facade can create them. Example:
ReportFacade can create internal PDFGenerator and ChartRenderer, but should receive DataRepository via constructor.Method Granularity: Facade methods should represent business operations, not one-to-one mappings of subsystem methods. Wrong:
openGate(), closeGate(). Right: processEntry(), processExit(). Each facade method should orchestrate multiple subsystem calls to complete a meaningful task. If facade method just calls one subsystem method, it is likely unnecessary.Common Mistakes to Avoid
Mistake 1: God Object Facade
Adding every possible operation to a single facade. This violates Single Responsibility Principle (SRP). Solution: Create multiple focused facades. Example:
EntryFacade for vehicle entry, ExitFacade for vehicle exit, ReportFacade for administrative reports, rather than one ParkingLotFacade with 20 methods.Mistake 2: Leaking Subsystem Abstractions
Facade methods returning subsystem types forces clients to depend on subsystem. Wrong:
processEntry() returns ParkingSpot (subsystem type). Right: returns Ticket (facade type) which contains spot number as string. Client should not need to import subsystem classes.Mistake 3: No Error Handling Strategy
Letting subsystem exceptions bubble up unchanged exposes internal implementation. Solution: Catch subsystem exceptions and wrap in facade-specific exceptions or return Result objects. Example: catch
DatabaseConnectionException from SpotManager and throw ParkingSystemException with user-friendly message.Interview Tip: When drawing class diagrams in interviews, always show the relationship arrows. Facade to subsystems should be composition (◆ solid diamond) or aggregation (◇ hollow diamond), never inheritance (▲ triangle). Explain that facade delegates work rather than extending behavior.
Follow-up Variations
Variation 1: Design a notification system facade that can send via Email, SMS, and Push. How do you handle partial failures (email succeeds but SMS fails)? Answer: Use asynchronous notification with retry queues. Facade returns immediately after queuing requests, subsystems process independently with dead-letter queues for failures.
Variation 2: In a multi-tenant system, should each tenant have its own facade instance? Answer: Depends on state. If facade is stateless (just coordinating), single instance serves all tenants by passing tenant context as parameter. If facade caches tenant-specific data, use instance per tenant or thread-local storage. Prefer stateless design.
Variation 3: How would you version a facade API as subsystems evolve? Answer: Create new facade version (for example,
PaymentFacadeV2) while keeping old version. Use Adapter Pattern inside new facade to map to changed subsystems. Deprecate old facade gradually. Alternatively, use feature flags within single facade to toggle between old and new behavior.💡 Key Takeaways
✓Facade should not prevent direct subsystem access, it provides convenience not enforcement
✓Implement compensating actions (rollback) when subsystem operations fail mid-workflow
✓Avoid God Object by creating multiple focused facades for different responsibilities
✓Facade methods should represent business operations, not one-to-one subsystem mappings
✓Use dependency injection for subsystem dependencies to enable testing with mocks
📌 Examples
1In elevator system, <code>ElevatorControlFacade</code> coordinates <code>MotorController</code>, <code>DoorController</code>, <code>FloorSensor</code> for <code>moveToFloor()</code> operation
2In vending machine, <code>VendingFacade</code> coordinates <code>InventoryManager</code>, <code>PaymentProcessor</code>, <code>DispenserUnit</code> for <code>purchaseItem()</code>