Adapter & Facade in Java
Converting interfaces; simplifying subsystems.
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);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]);[p, q] p[x, y] x[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 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);
}
}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.
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
- Adapter: changes the interface, same underlying job
- Facade: a simpler interface over many classes
- An adapter usually wraps one object; a facade coordinates several
- 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.
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]);- a
- z
- Throws UnsupportedOperationException
- 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);- [a, b, c]
- Throws UnsupportedOperationException
- Throws ArrayIndexOutOfBoundsException
- 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.