Adapter Design Pattern
Overview
The Adapter Design Pattern is a structural design pattern and is also known as the Wrapper Design Pattern. This design pattern acts as a bridge between two different interfaces. It can convert the interface of a class, to make it compatible with a client who is expecting a different interface, without changing the source code of the class.
When Will We Need Adapter Design Pattern?
As said earlier, an adapter design pattern acts as a link between two different interfaces. Lets us take a few examples to understand this:
- Like we have a card reader adapter which acts as a link between our computer and memory card.
- Another example will be a charging adapter that acts as a link between a device and the charging port.
Now let's take an example and try to see how can we implement an adapter design pattern to solve that problem.
Let us say we have an image showing application that can show only jpeg images, but we want to use an advanced image application that is capable of showing png and jpg files too. So we can use Adapter Design Pattern here to act as a link between these two different interfaces.
How Does the Adapter Design Pattern Work?
We have an ImageViewer interface and a concrete class named GalleryApp which is implementing the ImageViewer interface. GalleryApp can show jpeg files by default.
Let us say we have another interface named AdvancedImageViewer and concrete classes implementing this interface. These classes can show png and jpg files by default.
Now we want our GalleryApp class to be able to show png and jpg files without changing the source code of the ImageViewer interface.
So here we will use an adapter design pattern to solve this problem.
Implementation of Adapter Design Pattern
So we can use an Adapter design pattern to achieve this. We will create a ImageAdapter which implements ImageViewer and uses a AdvancedImageViewer object to show the desired image format.
Our Gallery application will use the ImageAdapter and simply pass the desired image format without worrying about which class can show what image format.
Structure of Adapter Design Pattern
Pseudo-Code of Adapter Design Pattern
Code Implementation of Adapter Design Pattern in Java
Step 1
Create interfaces for ImageViewer and AdvancedImageViewer.
ImageViewer.java
AdvancedImageViewer.java
Step 2
Create concrete classes implementing the AdvancedImageViewer interface.
PngShower.java
JpgShower.java
Step 3
Create adapter class implementing the ImageViewer interface.
ImageAdapter.java
Step 4
Create a concrete class implementing the ImageViewer interface.
GalleryApp.java
Step 5
Use the Gallery to show different types of image formats.
AdapterPatternDemo.java
Step 6
Verify the output.
As we can see that we have successfully used an adapter design pattern to the GalleryApp which even though implemented only the ImageViewer interface can show image formats that are supported by the AdvancedImageViewer interface using our ImageAdapter.
Code Implementation of Adapter Design Pattern in C++
Step 1
Create abstract class for ImageViewer and AdvancedImageViewer.
ImageViewer.cpp
AdvancedImageViewer.cpp
Step 2
Create concrete classes implementing the AdvancedImageViewer abstract class.
PngShower.cpp
JpgShower.cpp
Step 3
Create adapter class implementing the ImageViewer abstract class.
ImageAdapter.cpp
Step 4
Create a concrete class implementing the ImageViewer abtract class.
GalleryApp.cpp
Step 5
Use the Gallery to show different types of image formats.
AdapterPatternDemo.cpp
Step 6
Verify the output.
As we can see that we have successfully used an adapter design pattern to the GalleryApp which even though implemented only the ImageViewer interface can show image formats that are supported by the AdvancedImageViewer interface using our ImageAdapter.
Pros and Cons of Adapter Design Pattern
Pros
- Separation of Concern: We can separate the interface or data conversion code from the main business logic part of the code.
- Independence of Code: We can implement and use the various adapters without breaking the existing client or main code.
Cons
- We have to write a lot of code and it can decrease the efficiency. Sometimes it will be simpler to just change the code of a particular interface.
Relations of Adapter Design Pattern with Other Patterns
-
Adapter is commonly used with an existing interface to make some otherwise-incompatible classes work together consistently. On the other hand, Bridge is usually designed up-front, letting you develop parts of an application independently of each other.
-
Decorator supports recursive composition, which isn’t possible when you use Adapter. In addition, Adapter changes the interface of an existing object, while the Decorator enhances an object without changing its interface.
-
Adapter provides a different interface to the wrapped object, Decorator provides it with an enhanced interface and Proxy provides it with the same interface.
-
Facade defines a new interface for existing objects, whereas Adapter tries to make the existing interface usable. Adapter usually wraps just one object, while Facade works with an entire subsystem of objects.
-
Bridge, State, Strategy (and to some degree Adapter) have very similar structures. Indeed, all of these patterns are based on composition, which is delegating work to other objects. However, they all solve different problems. A pattern isn’t just a recipe for structuring your code in a specific way. It can also communicate to other developers the problem the pattern solves.
Embark on a design odyssey with our Instagram System Design course, where each lesson propels you closer to mastery.
FAQs about Adapter Design Pattern
Q. Which design problems does the adapter design pattern solve?
A. The adapter design pattern solves problems like: Reusing a class that does not have an interface that a client requires and making classes that have incompatible interfaces work together.
Q. What are the two variations of the adapter design pattern?
A. Two Variants of Adapter Pattern: Class Adapter and Object Adapter.
Q. What is the difference betwwen Class Adapter and Object Adapter?
A. Class Adapter as the name suggests can only wrap classes and not interfaces. It uses inheritance to achieve this. Object Adapter can wrap both classes and objects and it uses composition to do this.