Distinguish listener and callback adapters from dependency wrappers so Java adapter code stays purposeful instead of generic.
Java uses the word “adapter” in two related but different ways.
An interface adapter exists to make a large callback interface easier to consume. Older Java APIs use this heavily:
1public class WindowAdapter implements WindowListener {
2 @Override public void windowOpened(WindowEvent e) {}
3 @Override public void windowClosing(WindowEvent e) {}
4 @Override public void windowClosed(WindowEvent e) {}
5 // more default no-op methods
6}
This lets a client override only the callback methods it cares about. The purpose is ergonomics.
An implementation adapter sits at a dependency boundary and translates one application-facing interface to a concrete external API:
1public final class StripePaymentAdapter implements PaymentProcessor {
2 private final StripeClient client;
3
4 public StripePaymentAdapter(StripeClient client) {
5 this.client = client;
6 }
7
8 @Override
9 public Receipt charge(Money amount, String token) {
10 return StripeMapper.toReceipt(client.charge(amount, token));
11 }
12}
The purpose here is architectural isolation, not callback convenience.
If you confuse the two, design discussions get muddy. A Swing-style adapter class is about making a verbose interface pleasant to implement. A structural adapter in the Gang of Four sense is about translating one contract into another.
Java now also uses default interface methods and lambdas to solve many callback ergonomics problems that older adapter base classes handled. That means modern Java application code more often uses implementation adapters than interface adapters.
Ask which of these problems you are solving:
They both involve the word adapter, but they are not the same design move.