Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight
HomeLearnSystem DesignLow-Level Design & Design PatternsStructural Design Patterns
✓ FreeBeginner· 7 min read

Adapter & Facade

Adapter converts an interface a client already depends on; Facade hides a whole subsystem's complexity behind one simple entry point. Built through a third-party PaymentGateway wrapper.

Published September 22, 2026


Adapter & Facade

Both patterns hide something behind an interface — but they solve opposite-shaped problems. Adapter makes one existing interface look like another; Facade makes many things look like one.

Adapter: making an incompatible interface fit

The canonical trigger: your code depends on interface A, but you need to use a third-party (or legacy) class that implements interface B — and you can't change either one.

// Your internal interface, used everywhere in your codebase
interface PaymentProcessor {
    void charge(String userId, double amount);
}

// Third-party SDK — a completely different shape, you don't own this code
class StripeSdkClient {
    void createCharge(int amountInCents, String customerToken) { /* Stripe's own API */ }
}

// Adapter: makes StripeSdkClient satisfy PaymentProcessor
class StripeAdapter implements PaymentProcessor {
    private final StripeSdkClient stripeClient;

    StripeAdapter(StripeSdkClient stripeClient) { this.stripeClient = stripeClient; }

    @Override
    public void charge(String userId, double amount) {
        int cents = (int) Math.round(amount * 100);       // unit conversion the two APIs disagree on
        String token = lookupStripeToken(userId);          // concept translation: userId -> Stripe's customer token
        stripeClient.createCharge(cents, token);
    }

    private String lookupStripeToken(String userId) { /* ... */ return "tok_..."; }
}

Every other class in the codebase depends only on PaymentProcessor — swapping payment providers later means writing a new adapter, not touching any calling code. This is Dependency Inversion in action (see the Dependency Inversion lesson): the adapter is exactly the piece that lets a high-level PaymentProcessor-consuming class stay decoupled from a specific low-level SDK.

Facade: one simple door in front of a complex subsystem

Where Adapter translates between two interfaces, Facade doesn't translate anything — it just hides a subsystem's internal complexity (multiple classes, a specific call order, error handling) behind one simplified method.

// The complex subsystem — each class has real responsibilities, correctly separated (SRP)
class InventoryService { boolean reserve(String sku, int qty) { /* ... */ return true; } }
class PaymentService { String charge(String userId, double amount) { /* ... */ return "txn_1"; } }
class ShippingService { void scheduleDelivery(String orderId) { /* ... */ } }
class NotificationService { void sendConfirmation(String userId) { /* ... */ } }

// Facade: one call for the common case, hiding the orchestration
class CheckoutFacade {
    private final InventoryService inventory = new InventoryService();
    private final PaymentService payment = new PaymentService();
    private final ShippingService shipping = new ShippingService();
    private final NotificationService notifications = new NotificationService();

    void placeOrder(String userId, String sku, int qty, double amount) {
        if (!inventory.reserve(sku, qty)) throw new IllegalStateException("Out of stock");
        String txnId = payment.charge(userId, amount);
        shipping.scheduleDelivery(txnId);
        notifications.sendConfirmation(userId);
    }
}

Callers of CheckoutFacade.placeOrder(...) don't need to know the correct call order, or that four separate services are involved at all. Critically, the Facade doesn't replace the subsystem's own well-factored classes (each still has a single responsibility) — it just adds a simplified entry point on top for the common case, while advanced callers can still reach the individual services directly if they need finer control.

The distinction that matters in an interview

Adapter's job is interface translation — same underlying behavior, different shape, because you're bridging two things that were never designed to work together. Facade's job is complexity hiding — the subsystem behind it was designed by you, cooperatively, and the facade is just an ergonomic simplification, not a translation between incompatible contracts.

Follow-up questions this topic invites — and their answers

Q: Can Adapter wrap more than method-signature differences — e.g. different error-handling conventions? A: Yes — a common real case is adapting a third-party API that returns error codes into one that throws your codebase's own exception types, or adapting a callback-based API into a CompletableFuture-returning one. The translation isn't limited to parameter shapes.

Q: Does a Facade violate the Single Responsibility Principle by touching four services? A: No — SRP is about a class having one reason to change; the Facade's one reason to change is "the checkout orchestration sequence changes," which is a single, cohesive responsibility (see Single Responsibility & Open/Closed), distinct from each underlying service's own responsibility.

Q: When would you need two Adapters for the same third-party class? A: When two different parts of your codebase depend on two different internal interfaces that the same third-party class needs to satisfy — each adapter translates to a different target shape, since Adapter is defined by the pair of interfaces it bridges, not just the source class.

Q: Is a Facade the same as a Service Layer in a typical backend architecture? A: Conceptually very similar — a service-layer method that coordinates several repositories/lower-level services behind one method signature is Facade applied at the application-architecture level, not just within a single class.

Previous

Prototype Pattern

Next

Decorator Pattern

AI Tutor

Lesson: Adapter & Facade

Quick actions

AI responses can be inaccurate. Verify critical information.