Design Pattern Evangelist Blog

Smart pointers about software design

Adapter Design Pattern

What we've got here is... failure to communicate. Maybe there's a cool pattern that could give us a hand with that.


Electrical Plug Adapters

Introduction

You’re traveling internationally, and your electrical devices won’t work in your destination(s). You’ll need to take a set of electrical adapter plugs much like the ones shown above. You plug the adapter into the electrical outlet, and then you plug your device into the adapter. The adapter plug accommodates different outlet shapes as well as voltage, current frequency, and other differences.

The Adapter Design Pattern is much the same. It tends to be a relatively simple class that allows two classes to interact when their APIs don’t directly allow it.

Adapter continues the main theme of the Command, Strategy and Template Method design patterns – polymorphism. But Adapter sometimes adds another trick, delegation, or inheritance. Other design patterns use these, but Adapter uses them in a special way.

Adapter is about a change in the contract interface but not a change in behavior.

Structure

The previous design patterns, mentioned above, contain extending classes but for the most part, they aren’t the main features of those designs. Adapter features the extending classes showing how they use delegation or inheritance to bridge the communication gap.

Adapter Scenario

Before getting into the nuts-and-bolts, let’s start with a scenario. We start with a Target interface that declares a request() method.

Target Interface

We have a Client that follows the design principle to Program to an interface, not an implementation, so it delegates to Target.

Client Target Relationship

If I were describing Command or Strategy, then the next diagram would add a concrete class extending from Target that implements request(), and we’d be done. But in this scenario, the desired behavior has already been implemented in another class, Service via a method called action(). Now we have this:

Adapter Scenario

We have a few problems. Command and Strategy are based upon a plug-in technique where the extending concrete class plugs into the interface. The extending concrete needs to know about and implement the interface method(s). But Service doesn’t implement Target. We can’t plug it in.

What are our options?

Two Adapter Design

Adapter can bridge this gap, and there are two variations of Adapter:

I think better terms would have been Composition Adapters and Inheritance Adapter respectively, but no one asked me. They compare and contrast in the same way that the Strategy and Template Method do. Both pairs of patterns solve their similar problems, but in different ways with one favoring composition and the other favoring inheritance. Neither is necessarily better or worse than the other. Both mechanisms have their own strengths and weaknesses.

Regardless of the technique, Adapter allows two classes to communicate when they are not designed to communicate. In our scenario, the Client ultimately wants to access Service, but Service doesn’t fit in the Client/Target ecosystem. Adapters are translators. They translate the nomenclature of the Client with the nomenclature of the Service.

Object Adapter

The Object Adapter is based upon composition and delegation. Here are the basic elements:

Object Adapter

That’s it … mostly. The field attributes still need to be resolved. (See: Factory Method and Dependency Injection)

Class Adapter

The Class Adapter is based upon inheritance and tradition. Here are the basic elements:

Class Adapter

We still need to resolve a field attribute, but it’s not quite as much to set up as with the Object Adapter technique.

Both Adapter approaches work. I tend to prefer Object Adapters, but Class Adapters work as well. It depends upon whether you prefer composition or inheritance.

Pairs With Strategy

Adapter is rarely designed without it being paired with Strategy. Let me rephrase that. Adapter is Strategy. The only difference is that we have a little more implementation detail in Adapter in that it delegates to another class and translates API differences. Do a Google Image Search for Adapter Design Pattern UML class diagram and you’ll see the telltale signs for Strategy as well.

Summary

The Adapter Design Pattern allows one class to access another class even when their APIs differ. However, the adapted class needs to be similar enough in intent so that using an Adapter makes sense. Adapters might need additional implementation to translate argument types and return types as well, which was not shown in the diagrams here.

The Adapter Design Pattern does one more thing, which I haven’t mentioned yet. It helps keep the implementation modular and loosely coupled. The Client/Target code still doesn’t know about the Service code and vice versa even after being bridged by the Adapter. If Service changes its contract interface, then an Adapter based design may be able to absorb the impact of the interface change in the Adapter without any change to the Client/Target code.

Adapter implementations tend to be small. Each method is usually only a few lines long.

References

There are many online resources with diagrams and implementations in different programming languages. Here are some free resources:

Here are some resources that can be purchased or are included in a subscription service:

Comments

Previous: Template Method Design Pattern

Next: Façade Design Pattern

Home: Design Pattern Evangelist Blog