Conceptly
← All Concepts
πŸ”Œ

Adapter

StructuralA structural pattern that bridges incompatible interfaces

Adapter is a structural pattern that bridges two incompatible interfaces by sitting between them and translating calls. When the interface the client expects (Target) differs from the interface of the class you want to use (Adaptee), the Adapter converts calls between the two. It works just like a power plug adapter. You cannot plug a US plug into a Korean outlet, but with an adapter in between, the electricity flows just the same. In software, the Adapter's starting point is a situation where only the interface is mismatched while the underlying functionality is perfectly usable.

β–ΆArchitecture Diagram

πŸ” Structure

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

As projects grow, the need to integrate external libraries, legacy modules, and third-party APIs becomes routine. The problem is that their interfaces do not match what your code expects. Method names differ, parameter orders differ, return types differ. If you modify the client code to match the external interface, then replacing the library later forces changes across the entire client. If you try to modify the external code, the source may not be available, or modifying it makes future updates difficult. You need a way to connect the two without touching either side.

Why did this approach emerge?

Adapter is one of the 23 design patterns documented by GoF (Gang of Four) in 1994. As object-oriented programming became widespread, combining class libraries built by different teams grew common. With more commercial libraries whose source code could not be modified, a structural way to resolve interface mismatches without code changes became necessary. That pressure is identical today. npm packages, REST APIs, legacy microservices -- situations where 'it works but the interface does not fit' arise daily.

How does it work inside?

Adapter's core splits into three roles. The Client knows and calls only the Target interface's methods. The Adaptee has the actual functionality but exposes a different interface. The Adapter implements the Target interface and internally calls the Adaptee's methods, transforming results as needed. The sequence works like this: 1. The Client calls the Target interface's `request()`. 2. Inside the Adapter's `request()`, the Adaptee's `specificRequest()` is called. 3. The result from the Adaptee is transformed into the form the Client expects and returned. There are two implementation approaches. An object adapter holds the Adaptee as a field and delegates via composition. A class adapter inherits from the Adaptee and overrides methods. In most practical situations, composition is more flexible. Inheritance requires a language that supports multiple inheritance and tightly couples the Adapter to a single Adaptee.

What is it often confused with?

Adapter and Facade both wrap existing code to expose a different interface, so they can look similar. But the intent differs. Adapter's purpose is to make one incompatible interface conform to an existing interface. The wrapping target is typically one object, and interface conversion is the core concern. Facade's purpose is to simplify multiple subsystems behind a single entry point. Adapter and Decorator are also structurally similar. Both wrap a target object, but Adapter changes the interface while Decorator keeps the interface the same and adds functionality. The test for whether Adapter is right is 'Is the problem that the interface does not fit?' If the issue is missing functionality rather than mismatched shape, Adapter is not the right tool.

When should you use it?

Adapter appears most often at system boundaries. When replacing a payment gateway, you keep the existing `PaymentService` interface and wrap the new gateway's API with an Adapter so client code runs unchanged. The same approach works when switching ORMs or replacing an external authentication service. It is also useful in testing. Plugging a mock implementation into the same interface as the real HTTP client is a natural Adapter structure. However, if Adapters proliferate, it may be a signal to reconsider the interface design itself. If mismatches are structural, continually stacking conversion wrappers may be worse in the long run than redesigning a common interface.

Legacy integration -- converting an existing system's interface to fit new codeExternal library wrapping -- making a third-party API conform to your internal interfaceData format conversion -- processing XML responses in a JSON-based systemTest doubles -- swapping a real dependency for a test implementation through the same interface