Design Patterns - Adapter

carlillo

Carlos Caballero

Posted on March 22, 2019

Design Patterns - Adapter

There are 23 classic design patterns, which are described in the original book,
Design Patterns: Elements of Reusable Object-Oriented Software. These patterns
provide solutions to particular problems, often repeated in the software
development.

In this article, I am going to describe the how the Adapter Pattern; and how
and when it should be applied.

Adapter Pattern: Basic Idea

An adapter allows two incompatible interfaces to work together. This is the real-world definition for an adapter. Interfaces may be incompatible, but the inner functionality should suit the need. The adapter design pattern allows otherwise incompatible classes to work together by converting the interface of one class into an interface expected by the clients. — Wikipedia

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces. — Design Patterns: Elements of Reusable Object-Oriented Software

The main feature of this pattern is reusing a class which has different interfaces compared with the rest of classes or several classes which have different interface so they can works together.

There are two versions of this pattern:

  • The object adapter implements the target interface by delegating to an adaptee object at run-time.
  • The class adapter implements the target interface by inheriting from an adaptee class at compiler-time.

Since multiple inheritance is not supported by many languages including Java and
is associated with many problems we have not shown implementation using class adapter pattern.

To sum up, the object adapter (AKA adapter) contains an instance of the class it
wraps. The UML’s diagram of this pattern is the following one:

The Adaptor class contains the Adaptee class. Which meansAdaptee class will be used by Adaptor.

Adapter Pattern: When To Use

  1. There is a class which its interfaces do not match the one you need.
  2. There are several subclasses but it’s unpractical to adapt their interface by subclassing every one.

The Adapter Pattern has several advantages, summarised in the following points:

  • The code is more resuable and flexible.
  • Clean code because the client/context doesn’t use a different interface in each concrete class and can use polymorphism to swap between different adapters.

Adapter pattern — Example 1: A new Android arrives to the city example using JavaScript/TypeScript

I will now show you how you can implement this pattern using JavaScript/TypeScript. Please bear in mind that Javascript lacks both interfaces and abstract classes. Therefore, the best way to understand this pattern is by using an example and TypeScript. In our case, I have made up a problem in which there is an abstract class named Warrior which defines a Warrior. A warrior has a set of attributes not relevant to the problem and a method called attack. There is a classification of types of warriors such as Saiyan and Namekian which defines a concrete implementation of the attack method but a new class arrives to the system called Android which does not satisfy Warrior's interface but internally implemented the method just in different way. The following UML diagram shows the scenario that I have just described.

The solution is to use an adapter pattern that consits in a class (AndroidAdapter) which contains the Android object and use it to do it compatible with the warrior's interface. I.e, the new UML diagram using the adapter pattern is shown below:

The code associate to the models and interface are the following ones:

As you can see the Android class has not implemented the warrior's interface.
So, the class AndroidAdapter is responsible for solving this problem.

Finally, the client/context that wants to use the three class should use the AndroidAdapter class together with Saiyan and Namekian as you can see in the next code:

Adapter pattern — Example 2: Several races want to works together (Genki-dama)

using JavaScript/TypeScript

Another interesting problem which is resolved using Adapter pattern is when there are several classes with different interfaces but they can works together. In the following UML’s diagram you can see this situation:

In this case, the races have different interface to communicate between them. In concrete, each race has one or several methods to shared its power. For example, the humans have sharedPower and the namekians have getPower and even more complex are the saiyans which have two methods to shared its power (myPowerPart1 and myPowerPart2).

The solution to do that several races works together is used the adapter pattern as you can see in the following UML’s diagram.

A new adapter class is used for each class, this adapter class contains the original object and the methods that implements the interface. The code for this example is quite easy.

And their respective adapters are the following:

Finally, all the objects contributing energy to fight evil and achieve great power.

I have created two npm scripts that run the two examples shown here after applying the Adapter pattern.

npm run example1
npm run example2

Conclusion

Adapter Pattern can avoid duplicated code in your project, when there are class that can work together but their interface are not compatible. In this post you have been able to have a look a simple implementation using JavaScript/TypeScript language.

The most important thing has not implement the pattern as I have shown you, but to be able to recognise the problem which this specific pattern can resolve, and when you may or may not implement said pattern. This is crucial, since implementation will vary depending on the programming language you use.

More more more...



Originally published at www.carloscaballero.io.

💖 💪 🙅 🚩
carlillo
Carlos Caballero

Posted on March 22, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related