A Complete Guide to Structural Design Patterns in Java: The Adapter Pattern

·

3 min read

What is a design pattern?

A software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design.

Why should I learn patterns?

Makes life simpler by not reinventing the wheel

  1. Toolbox of time-tested solutions to common problems in software design.

  2. Defines a common language between the team and organization to solve emerging issues related to technological advancements.

  3. Start understanding patterns in libraries and languages.

Classification of patterns

Creational

Structural

Behavioral

There are 7 types of Structural Design patterns:

  1. Adapter

  2. Bridge

  3. Facade

  4. Decorator

  5. Flyweight

  6. Composite

  7. Proxy

In this article, we will focus in detail on the Adapter design pattern.

Usage:

Let classes work together which are otherwise incompatible

It allows objects with incompatible interfaces to collaborate by combining the capability of two independent interfaces.

Existing problem:

There is a class(Client) that expects certain objects to work with.

Suddenly, there is a new requirement that the client class needs to work with a completely different object which is not compatible with the existing ones.

Real-life example:

The mobile charger that we use was invented due to the difference between voltage requirement of the mobile charging socket and the wall socket.

Mobile battery needs 3 volts to charge but the normal socket produces either 120V - 240V . So the mobile charger works as an adapter between mobile charging socket and the wall socket.

How can the Adapter pattern help?

By converting the interface of a class into another interface clients expect.

There will be an Adapter class as an intermediary and will implement the existing interface. It will be composed of the new interface.

The client now makes a request to the adapter(unaware that it is the adapter because the Adapter still implements the existing interface) by calling a method on it using the target interface.

The adapter translates that request on the adaptee using the adaptee interface.

Below is the UML diagram:

Image Credits — GeeksForGeeks

Code:

We have a toy RabbitSimulator class that tests the sounds made by different types of toy rabbit instances.

Let’s assume that we are short on toy rabbit objects and we would like to use Turkey objects in their place. Turkeys have some similar functionality but implement a different interface, so we can’t use them directly.

Below is the client code which produces various toy rabbits:

Output:

Below is the Rabbit interface:

Below are the concrete implementation of breeds of rabbit:

Belgian Hare —

Himalayan —

Introducing the Turkey interface which now needs to be accommodated in the client class that we discussed above.

Concrete implementation of above Turkey Interface:

WildTurkey —

Due to difference in interface, we will use a ‘TurkeyAdapter’ class that will implement Rabbit interface but Turkey interface will be the adaptee.

Below is the code for TurkeyAdapter:

Notice, how we added the custom implementation of Turkey’s behavior to the overridden methods.

Here is the final modified client code : (without breaking any existing logic)

Output:

Thus, with the help of Adapter pattern we have been able to accommodate a completely new interface in existing client class without modifying the client code at all.

If you liked this article, please click the “clap” button 👏 a few times.

Gives me enough motivation to put out more content like this. Please share it with a friend who you think this article might help.

Follow me Varsha Das to receive my weekly articles.

Connect with me — Varsha Daxs | LinkedIn

Follow my Youtube channel — Code With Ease — By Varsha, where we discuss Data Structures & Algorithms.

Thanks for reading.

Happy learning! 😁