SwadhyAI Notes

All Low-Level Design notes

One foreign type

Adapter

Adapter changes the method shape of one existing class so it matches an interface you already use. Example: StripeClient cannot be Payable until a small translator maps cents and charge ids.

Full Adapter page

Many familiar types

Facade

Facade gives one simple method in front of several classes you already own. Inventory, Payable, Invoice, and Mailer already speak fine — the caller should not have to orchestrate all of them.

Full Facade page

If you call both “a wrapper,” you will pick the wrong one in an interview.

One sentence

Am I changing one foreign interface to match mine, or hiding many classes behind one friendly method?

changes a foreign interface to match yours. keeps the existing interfaces and hides many classes behind one friendly method.

Same checkout, two different objects

Adapter · change shape

StripeClient.charge(token, cents) cannot be Payable.pay(Money, orderId) until a translator sits in the middle. After the adapter, you still have one collaborator — it just speaks your language. This means the number of objects did not go down. Only the shape of the call changed.

Facade · reduce count

Inventory, Payable, InvoiceService, and Mailer already have fine APIs. The pain is that every controller must remember the sequence. CheckoutFacade.placeOrder does not rename those APIs. It stops the rest of the app from calling them directly.

Decision grid — fill this on the whiteboard

AskAdapterFacade
How many types sit behind the wrap?One foreign classSeveral familiar classes
What changes?Method names, argument types, return typesHow many collaborators the caller must know
Do the inner APIs stay?No — they cannot be your interface without mappingYes — Inventory is still Inventory
After the wrap, collaborator countStill oneDropped from many to one entry point
Typical smellcharge(token, cents) is not pay(Money, id)Controller calls reserve, pay, invoice, mail
Wrong name in interviewsCalling a four-service door an AdapterCalling a Stripe rename a Facade

Adapter: one class, wrong shape

java
class LegacyPrinter { void output(byte[] raw) { } }

interface ReceiptPrinter {
  void print(Receipt receipt);
}

class LegacyReceiptAdapter implements ReceiptPrinter {
  private final LegacyPrinter legacy;

  public void print(Receipt receipt) {
    legacy.output(receipt.toBytes());
  }
}

Facade: many classes, one door

java
class HotelFrontDesk {
  private final Reservations rooms;
  private final Billing billing;
  private final Housekeeping housekeeping;

  KeyCard checkIn(Guest guest, Dates stay) {
    Room room = rooms.allocate(stay);
    billing.openFolio(guest, room);
    housekeeping.prepare(room);
    return room.keyCard();
  }
}

They compose. They are not synonyms.

A facade may hold an adapter: placeOrder talks to Payable, and Payable happens to be StripePayableAdapter. That is healthy. What is not healthy is using Adapter when the smell is “too many collaborators,” or Facade when the smell is “wrong method names on one SDK.”

Controller │ placeOrder(cart) ▼ CheckoutFacade ← facade (many types → one method) ├── Inventory.reserve ├── Payable.pay ← target interface │ └── StripePayableAdapter ← adapter (wrong shape → your shape) │ └── StripeClient.charge ├── InvoiceService.issue └── Mailer.sendReceipt
java
class CheckoutFacade {
  private final Inventory inventory;
  private final Payable payment; // often a StripePayableAdapter
  private final InvoiceService invoices;
  private final Mailer mailer;

  Receipt placeOrder(Cart cart) {
    inventory.reserve(cart.lines());
    PaymentResult paid = payment.pay(cart.total(), cart.id());
    Invoice invoice = invoices.issue(cart, paid);
    mailer.sendReceipt(cart.email(), invoice);
    return new Receipt(invoice.id(), paid);
  }
}

Two other wrappers steal the same word

Interviewers will say “you wrapped it.” Name the intent. Four short lines on the whiteboard are enough.

Adapter

Changes shape. One foreign type → your type.

Facade

Reduces how many types you see. Many → one entry point.

Decorator

Same interface, extra behavior (log, retry, compress). Stackable. Inner already lives.

Proxy

Same interface, control access / lazy create / remote. Rarely stacked as features.

Whiteboard test — fill left or right, never “wrapper”

Draw two columns. Left column: “Does the inner type fail to compile as my interface?” If yes, use Adapter. Right column: “Does the caller name four types to finish one use case?” If yes, use Facade. If both are true in checkout, draw both boxes and a line from Facade.Payable to the adapter. If neither is true, you are in Decorator or Proxy territory — same interface, with either extra behavior or control of access/lifetime/location.

Compile test

Could StripeClient implement Payable without mapping? No → Adapter.

Collaborator-count test

Does the controller list four collaborators? Yes → Facade.

Same-type test

Still Notifier / Image? Then Decorator or Proxy, not this page.

Adapter for a crowd of classes

If the caller must talk to five services, a translator for one of them does not help. Give them a facade. Adapt a vendor only where the type itself is foreign.

Facade for a mismatched SDK

A “StripeFacade” that only renames charge to pay is an adapter with a louder name. Facade is for a subsystem. One SDK with the wrong signature is Adapter.

Pick in ten seconds

Legacy printer with output(byte[])

Adapter. One foreign method list. ReceiptPrinter is your target.

Kiosk must allocate room, open folio, prep housekeeping

Facade. Three familiar services, one checkIn.

Need retries around Payable after Stripe is adapted

Decorator on Payable. Not a second adapter. Not a facade.

Gallery must not load DiskImage until display

Proxy. Same Image type, delayed creation. Not Adapter — the type already matches.

placeOrder uses Payable which is StripePayableAdapter

Both: Facade for the sequence, Adapter for the SDK. Say both sentences.

How to explain this in an interview

“Adapter changes a foreign interface to match ours. Facade keeps interfaces and hides many classes behind one method. Decorator adds behavior on the same type. Proxy controls access, lifetime, or location. If I mix those four words, I fail the structural round.”
  1. Someone draws one box labeled Wrapper around Stripe and Inventory. Split it. What is each box?
  2. Write the one-sentence test you will use when the interviewer says “just wrap it.”

Takeaway

Adapter changes shape. Facade changes collaborator count. They may sit in the same checkout, but they answer different questions. Name the question first, then the pattern.