Card 01/ 08

ConceptDifficulty: Intermediate3 min

Adapter Pattern: Making an Existing Class Fit the Interface a Client Expects

The class already does the job; only its method names and arguments are wrong.

The Adapter pattern converts the interface of an existing class into the interface a client expects, so the two can work together without either being changed. The adapter is a small class that implements the client's interface and passes each call on to the existing class, translating names, arguments and results on the way. This card covers the mismatch that calls for one, the intent, and when the pattern is the right tool.

The mismatch appears when a useful class has the wrong shape. A checkout is written against pay(amount), and the company's old payment gateway offers make_transaction(cents, currency). The gateway works and other systems use it, so it cannot change. Without an adapter, the checkout learns the gateway's interface, and every place that pays now knows about cents and currency codes.

A client that knows the foreign class, and one that does not

Without the patternthe client branches on the gateway

py
def complete(self, total):
    if isinstance(self.processor, LegacyGateway):
        cents = int(total * 100)
        result = self.processor.make_transaction(cents, "GBP")
        return result["status"] == "OK"
    return self.processor.pay(total)

Each new gateway adds a branch, in every method that pays.

With the patternone adapter, and the client unchanged

py
def complete(self, total):
    return self.processor.pay(total)


checkout = Checkout(LegacyGatewayAdapter(LegacyGateway(), "GBP"))

The translation lives in one class, and the checkout never learns the gateway exists.

The Gang of Four state the intent as: convert the interface of a class into another interface clients expect, so that classes with incompatible interfaces can work together. The interface the client expects is the target, the existing class is the adaptee, and the class between them is the adapter.

Think of a travel plug adapter, which lets a British plug fit a European socket. The analogy breaks in one place: a plug adapter changes the shape of the plug and not the voltage, while a software adapter often has to convert what the values mean, such as pounds into pence, and not only rename the call.

Adapter is one of seven structural patterns, the family that composes classes and objects into larger structures.

The structural family, with this pattern marked
PatternWhat it does
Adapter (this topic)Gives an existing object the interface a client expects.
BridgeSeparates an abstraction from its implementation so both can vary.
CompositeTreats a tree of objects and a single object the same way.
DecoratorAdds behaviour by wrapping an object in another with the same interface.
FacadePuts one simple interface in front of a complex subsystem.
FlyweightShares the common part of many small objects to save memory.
ProxyStands in for an object to control access to it.
Adapter

Use it when

  • A class does the job but its interface does not match the one your code is written against.
  • The class cannot or should not be edited, because it is a library or other code depends on it.
  • Several classes with different interfaces must be used through one interface, such as several payment providers.

Avoid it when

  • You own both sides and can change one to match the other directly.
  • The interfaces differ in meaning and not only in shape, so a translation would hide a real difference.
  • The client needs a simpler view of many classes rather than a different view of one, which is Facade.

← → move through sections and cards