🏛️ Design Principles & Patterns · Advanced

Adapter & Facade in Java

Converting interfaces; simplifying subsystems.

🧩 The mysteryYour laptop plug doesn't fit the hotel socket, and the city is too complex to explore alone. One needs an adapter; the other, a concierge.

Adapter: change the plug

An Adapter converts one interface into the one clients expect. The job underneath stays the same; only the shape changes. Here a Fahrenheit sensor is made to look like the Thermo interface your code already uses.

class CelsiusAdapter implements Thermo {
    private final FahrenheitSensor s;
    CelsiusAdapter(FahrenheitSensor s) {
        this.s = s;
    }
    public double celsius() {
        return (s.readF() - 32) * 5 / 9;
    }
}

Adapters in the JDK

Arrays.asList(arr) adapts an array to the List interface. It's a view backed by the same array: no copy is made. InputStreamReader adapts a byte stream into a character Reader.

String[] arr = {"a", "b", "c"};
List<String> view = Arrays.asList(arr);
Reader r = new InputStreamReader(
    System.in, StandardCharsets.UTF_8);
🔮 Predict it

Two doors, one array

What does this print?

String[] arr = {"x", "y"};
List<String> view = Arrays.asList(arr);
arr[1] = "q";
view.set(0, "p");
System.out.println(view + " " + arr[0]);
  1. [p, q] p
  2. [x, y] x
  3. [p, y] x
Show the answer

The list and the array are the same storage. Writing arr[1] shows up in the list, and view.set(0, ...) shows up in the array. Both see [p, q].

⚠️ The trap

The fixed-size trap

An array can't grow, so the adapter can't either. set() works, but add() and remove() throw UnsupportedOperationException. Need a growable list? Copy it: new ArrayList<>(Arrays.asList(arr)).

List<String> view = Arrays.asList(arr);
view.set(0, "z"); // fine
view.add("c");    // throws!

Facade: one button for the show

A Facade gives a simple entry point to a complex subsystem. One method coordinates several objects. It doesn't lock the subsystem away: advanced clients can still use the lights or amplifier directly when they need more control.

class HomeTheater {
    void watchMovie(String title) {
        lights.dim(10);
        screen.down();
        amp.on();
        player.play(title);
    }
}
🤔 Think first

Adapter or Facade?

Your code expects a WeatherSource interface, but the only provider is an old XmlWeatherClient with totally different methods. Adapter or Facade? And how do you tell them apart in general?

Think about it, then reveal the answer

Adapter: you translate one object's interface into the one you need. A Facade instead coordinates several subsystem objects behind a few simple methods. Rule of thumb: adapter = different shape, same job; facade = simpler front for many parts.

💼 In the real world

Wrapping vendor SDKs

Teams wrap third-party SDKs in an adapter behind their own interface, like a PaymentGateway whose pay(Money) calls charge(cents, currency). Switching vendors then means one new class. Service layers act as facades over messy subsystems.

Key takeaways

  1. Adapter: changes the interface, same underlying job
  2. Facade: a simpler interface over many classes
  3. An adapter usually wraps one object; a facade coordinates several
  4. Both reduce coupling to code you don't control

💡 A travel plug adapter changes the plug shape; a hotel concierge is a facade for the whole city.

🤯 Did you know?

The popular SLF4J logging library is named after this pattern: it stands for Simple Logging Facade for Java.

Practice questions

What does this print?

String[] arr = {"a", "b", "c"};
List<String> view = Arrays.asList(arr);
view.set(0, "z");
System.out.println(arr[0]);
  1. a
  2. z
  3. Throws UnsupportedOperationException
  4. null
Check your answer

z. Arrays.asList returns a List adapter backed by the same array, so writes through the list change the array.

What does this print?

String[] arr = {"a", "b"};
List<String> view = Arrays.asList(arr);
view.add("c");
System.out.println(view);
  1. [a, b, c]
  2. Throws UnsupportedOperationException
  3. Throws ArrayIndexOutOfBoundsException
  4. Compile error
Check your answer

Throws UnsupportedOperationException. The adapter has a fixed size because the array underneath can't grow. set() is supported, but add() and remove() throw.

Next: a recipe card that fixes the order of steps, and an order ticket that can wait in a queue.