Also known as Wrapper

Adapter

Intent

Allows collaboration between objects with incompatible interfaces.

Problem

Imagine that you have an app that works with data in XML format, but at some point, you need to use a library that can only work with JSON.

For example, your app works with a stock data. It downloads data from multiple data providers in XML and builds nicely looking charts. In a new version, you decided to improve the app and use some smart analytics library. But there is a catch: the analytics library only works with data in JSON format.

Problem that Adapter solves

In cases like this, you could either rewrite your code to support JSON or change the library itself to work with XML. The first choice may break your existing code, and the second might simply be impossible if the library's code is unavailable.

Solution

You can create an Adapter. It's a translator object that converts calls from one object to the form that other object can understand. Adapters usually wrap one of the objects, to hide the complexity of translation from the other objects.

Adapters can convert not only the data format but also interfaces. For instance, an adapter may receive a call to method A and pass it to methods B, C and D of a wrapped object.

Sometimes it's even possible to create two-way adapters that can convert calls in both directions.

Adapter's solution

So, the stock market app we discussed above, would receive a special XML_To_JSON_Adapter class. It would wrap an object of analytics library and convert all incoming data from XML to JSON before passing it to methods of a wrapped object. This way, you won't need to change any existing code: neither app's classes, nor the analytics library.

Real-World Analogy

Power plugs and sockets in different countries

When you fly from the US to Europe for the first time, you may get a surprise when you try to charge your laptop. The power plug & sockets standards vary between countries. That's why your US plug will not fit the German socket.

The problem can be solved by a power plug adapter that has the American-style socket and the European-style plug.

Structure

Object adapter

This implementation uses composition principle: adapter implements the interface of one object and wraps the other one. It can be implemented in all major programming languages.

Adapter pattern structure (object adapter)

Class adapter

This implementation uses inheritance. Adapter inherits both interfaces at the same time. It can be implemented only in languages that support multiple inheritance, such as C++.

Adapter pattern structure (class adapter)
  1. Existing interface or class that is already supported by the rest of your code.

  2. Service is some useful class (usually 3rd-party or legacy) that can't work directly with application's classes.

  3. Adapter implements Existing interface and holds a reference to an object of the Service class.

    The adapter receives calls from client code via the methods of Existing interface. It may correct type or format of the data, passed through the parameters of these methods, before calling methods of the Service object and passing the data along.

  4. Client uses Adapter object through a Existing interface.

    This allows adding new Adapter classes to the program without changing existing code (this situation may arise when the Service class changes, for example, when you update the 3rd party library).

  5. The class adapter does not need to wrap any objects. It implements both interfaces at the same time. Thus it's compatible with both objects.

Pseudocode

Let's see how Adapter can convert one interface into another with some basic data conversion. The example is based on the conflict between round holes and square pegs. Round holes work great with round pegs; you can determine whether or not one fits another just by comparing their radiuses. But square pegs don't have the radius measurement at all.

Adapter pattern example

That's why we create an Adapter class that wraps square peg objects and pretends that it has a radius, which would be half of the square's diameter or, in other words, minimal radius of the circle that can contain that square.

// Classes with compatible interfaces: RoundHole and RoundPeg.
class RoundHole is
    constructor RoundHole(radius) { ... }
    method getRadius
    method fits(peg: RoundPeg) is
        return this.getRadius() >= peg.radius()

class RoundPeg is
    constructor RoundPeg(radius) { ... }

    method getRadius() is
        Return the peg radius.


// Obsolete incompatible class: SquarePeg.
class SquarePeg is
    constructor SquarePeg(width) { ... }

    method getWidth() is
        Return the square peg width.


// Adapter allows fitting square pegs into round holes.
class SquarePegAdapter extends RoundPeg is
    field peg: SquarePeg

    constructor SquarePegAdapter(peg: SquarePeg) is
        this.peg = peg

    method getRadius() is
        return Math.sqrt(Math.pow((peg.getWidth()/2), 2) * 2);


// Somewhere in client code.
hole = new RoundHole(5)
rpeg = new RoundPeg(5)
hole.fits(rpeg) // true

small_sqpeg = new SquarePeg(2)
large_sqpeg = new SquarePeg(5)
hole.fits(small_sqpeg) // won't compile (incompatible types)

small_sqpeg_adapter = new SquarePegAdapter(small_sqpeg)
large_sqpeg_adapter = new SquarePegAdapter(large_sqpeg)
hole.fits(small_sqpeg_adapter) // true
hole.fits(large_sqpeg_adapter) // false

Applicability

When you want to reuse existing class, but its interface is not compatible with the rest of application's code.

The Adapter pattern creates a middle layer class that translates application calls to the form that the existing class understands.

You need to reuse several existing classes, but they lack some common functionality. And you can't add it to the superclass because it's either closed or used in other code.

You could put the missing functionality into a new adapter class. It will connect your app's code and the classes you are interested in. This solution looks very similar to the Visitor pattern.

How to Implement

  1. Make sure that you have two actors:

    • Useful service objects.
    • Application code that has to use service objects. The application shouldn't be able to use the service objects directly, because of incompatible interfaces or data formats.
  2. Define the client interface that the future adapter class will be following. The application will use this interface to communicate with an adapter.

  3. Create an adapter class, make it implementing the client interface, but leave all methods empty for now.

  4. Add a field into the adapter class that will store a reference to a service object. In most cases, this field gets the value in a constructor. In simpler cases, the adaptee can be passed directly to the adapter methods.

  5. One by one, implement all methods of the client interface in adapter class. These methods should convert parameters into the appropriate format and pass them to methods of the service object.

  6. Once the adapter class is ready, use it in application code via the client interface.

Pros and Cons

  • Hides from the client code unnecessary implementation details of interface & data conversion.
  • Increases overall code complexity by creating additional classes.

Relations with Other Patterns

  • Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together. Adapter makes things work after they're designed; Bridge makes them work before they are.

  • Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.

  • Adapter is meant to change the interface of an existing object. Decorator enhances another object without changing its interface. Decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn't possible with pure Adapters.

  • Facade defines a new interface, whereas Adapter reuses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.

  • State, Strategy, Bridge (and to some degree Adapter) have similar solution structures. They all share elements of the "handle/body" idiom. They differ in intent - that is, they solve different problems.

Implementations in Different Programming Languages

Java