0/0
Design Patterns

Adapter Pattern

A structural pattern that makes two incompatible interfaces work together by wrapping one in a class that speaks the other β€” the wrapper changes nothing inside, it only translates on the way through.

Explore Topics

πŸ”Œ
Intent
Translate, don't rewrite
πŸ”Œ Adapter Workbench β€” three scenarios Γ— two wrap styles
US Laptop wants 110V. European wall socket gives 220V. Adapter halves the voltage on the way through.
πŸ›οΈ UML β€” Object Adaptercomposition
Client
USLaptop
depends on Target
β”‚ uses β–Ό
Target ⟨⟨interface⟩⟩
USOutlet
+ provide110V() : int
β–³β”„β”„ implements β”„β”„β”‚
Adapter
V220To110Adapter
βˆ’ wrapped : EuropeanSocket
+ provide110V() : int
◇━━ HAS-A ━━┃
Adaptee (legacy)
EuropeanSocket
+ produce220V() : int
πŸ“„ Java skeleton β€” Object Adapterimplements + HAS-A
class V220To110Adapter implements USOutlet { private final EuropeanSocket wrapped; // HAS-A public V220To110Adapter(EuropeanSocket w) { this.wrapped = w; } @Override public int provide110V() { return wrapped.produce220V() / 2; // forward + convert }}
Step 0 / 6
πŸ“œ Call Trace β€” laptop.charge(adapter)0 of 6
Press β–Ά Step to advance one call, or ⏭ Run to animate the entire trace.
Adapter's two defining axes: what you adapt (scenario chips) × how you wrap (Object vs Class). The UML arrow Adapter→Adaptee swaps between ◇ composition and △ inheritance when you flip the wrap style — the rest of the diagram is identical.
πŸ”Œ
Intent
Translate, don't rewrite

Adapter is a **structural** GoF pattern: *"Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces."* The Client speaks one language (the **Target** interface). The thing you actually want to call speaks another (the **Adaptee**). Neither side can be changed β€” the Client is shared infra, the Adaptee is legacy or third-party. So you write a thin **Adapter** that IS-A Target (so the Client accepts it) and either HAS-A or IS-A Adaptee (so it can forward and translate). The pattern is sometimes simply called **Wrapper** β€” but every wrapper that translates a different interface is an Adapter.

Key Ideas
  • Two interfaces, one bridge β€” Adapter exists to **reconcile** an interface mismatch, not to add behavior (that's Decorator) and not to control access (that's Proxy).
  • You touch neither side β€” the Client and the Adaptee are both untouchable; only the Adapter is yours to write.
  • Two variants: **Class Adapter** (extends Adaptee + implements Target β€” inheritance) and **Object Adapter** (implements Target + HAS-A Adaptee β€” composition). They have the same intent but different consequences.
  • The hallmark phrase is **code reuse for incompatible legacy** β€” wrap an already-tested class instead of forking it.
Strengths
  • ✦Lets you reuse an existing, already-tested Adaptee class without modifying it.
  • ✦The Client code never knows the Adaptee exists β€” it sees only the clean Target interface.
  • ✦Adding a new incompatible source is purely additive: write a new Adapter, the Client doesn't change (Open/Closed Principle).
Weaknesses
  • β–³Every call goes through one extra hop (the forward) β€” usually free, but visible in tight loops.
  • β–³It is sometimes tempting to ship many adapters when you could have just fixed the API β€” Adapter is a retrofit pattern, not a forward-looking design.
  • β–³The Adapter is one more class to read, name, and maintain β€” small but cumulative complexity.
Used in:A **RoundHole** only accepts pegs that report their radius. A **SquarePeg** reports only its width β€” wrong shape, wrong vocabulary. You can't change the hole (the building's infrastructure) and you can't modify the SquarePeg class (it ships in a library you depend on). A **SquarePegAdapter** implements the round-peg interface and computes the smallest enclosing radius from the wrapped square's width β€” and suddenly your SquarePeg fits through the round hole without either side noticing.
Code Snippets

Quiz

Intent Quiz
QUIZ 1/6
Which statement best captures the **intent** of the Adapter pattern?

Diagrams

Class Adapter β€” UML
Loading diagram...
Class Adapter uses inheritance: the Adapter extends Adaptee (inheriting its legacy method for free) and implements Target (so the Client accepts it). In Java this works only because Target is an interface β€” Java's single class inheritance forbids extends Adaptee extends Target at the same time. The Adapter is BOTH an Adaptee and a Target, which is sometimes useful and sometimes a leaky abstraction.
Object Adapter β€” UML
Loading diagram...
Object Adapter uses composition: the Adapter implements Target (so the Client accepts it) and holds a private Adaptee field that it forwards calls to. No Java inheritance restriction; the Adaptee can be swapped at runtime by passing a different instance into the constructor; subclasses of the Adaptee can also be adapted polymorphically. This is the variant you should default to in modern Java β€” composition over inheritance applies here cleanly.
Adapter vs Decorator β€” the wrapped object's interface is what differs
Loading diagram...
Both patterns wrap an object. The single distinction is the wrapped object's interface. In Adapter (left), the wrapper A_Adapter holds an A_Adaptee whose interface is different from the Target β€” the whole point of the pattern is to bridge that gap. In Decorator (right), the wrapper D_Decorator holds a D_Component whose interface is the same as the wrapper's own interface (both implement D_Component). This single difference cascades into every other contrast you have ever heard: Adapter is a retrofit applied once at a boundary; Decorator stacks arbitrarily deep because each layer matches the layer above. Adapter translates an interface; Decorator adds behavior while preserving the interface. If your wrapper has the same interface as what it wraps, you have written a Decorator; if it has a different interface, you have written an Adapter.

Practice

Classify each fragment under the Adapter variant it characterizes. Some are Java code, some are properties of the variant.
EXERCISE 1/4
extends LegacyAdaptee implements Target
implements Target with a private Adaptee field
Limited by Java's single class inheritance
Can adapt subclasses of Adaptee polymorphically
Adapter IS-A Adaptee (can be passed where Adaptee is expected)
Adapter constructor takes the Adaptee as a parameter
No forwarding field β€” inherited Adaptee methods are called directly
Adaptee instance can be swapped at runtime
Class Adapter
Object Adapter
Trace the Voltage Converter Object Adapter
EXERCISE 2/4
EuropeanSocket eu = new EuropeanSocket(); USLaptop laptop = new USLaptop(); // Statement 1 System.out.println(eu.produce220V()); // Statement 2 USOutlet adapter = new Voltage220To110ObjectAdapter(eu); System.out.println(adapter.provide110V()); // Statement 3 laptop.charge(adapter); // Statement 4 β€” chain through a fresh adapter on a fresh socket EuropeanSocket eu2 = new EuropeanSocket(); USOutlet adapter2 = new Voltage220To110ObjectAdapter(eu2); System.out.println(adapter2.provide110V() == adapter.provide110V());
Statement 1
Statement 2
Statement 3
Statement 4
Adapter vs Decorator vs Bridge β€” true or false?
EXERCISE 3/4
Adapter and Decorator are basically the same pattern β€” both wrap an object to enhance it.
In Java, the Class Adapter variant requires the Target to be an interface (not a class).
The Adapter pattern is forward-looking design β€” you should plan for it when designing a new system.
An Object Adapter cannot add any new behavior β€” it can only forward calls.
Bridge separates an abstraction from its implementation so they can vary independently; Adapter retrofits an existing class into an incompatible interface.
Object Adapter is generally preferred over Class Adapter in modern Java code.
Complete the Voltage Converter Object Adapter
EXERCISE 4/4
class Voltage220To110ObjectAdapter USOutlet { private final wrapped; public Voltage220To110ObjectAdapter( wrapped) { this.wrapped = wrapped; } @Override public int provide110V() { return / 2; } }

References

πŸ“š

Gamma, Helm, Johnson, Vlissides β€” Design Patterns: Elements of Reusable Object-Oriented Software (Adapter, pp. 139–150)

oreilly.com

book
πŸ“„

Refactoring.Guru β€” Adapter Pattern

refactoring.guru

article
πŸ“„

SourceMaking β€” Adapter Design Pattern

sourcemaking.com

article
πŸ“š

Freeman & Robson β€” Head First Design Patterns, 2nd Edition (Adapter & Facade, Ch. 7)

oreilly.com

book
πŸ“‹

Java SE Docs β€” java.io.InputStreamReader (a canonical Adapter in the standard library)

docs.oracle.com

docs