The Adapter design pattern is a structural design pattern that helps us to connect to the legacy or third-party code that exposes a similar functionality through a different interface.
A real-world analogy for an adapter is the one we use to connect our USB cable to an ethernet port.
While designing an object-oriented application, we might feel the need for an adapter when say our client expects an object of a specific type and we have a third-party API offering the same functionality but through an incompatible interface.
It’s also popularly known as a wrapper as it wraps an existing code with a new interface making it compatible for the client.
Let’s be aware of the terms we use when talking about an adapter pattern:
Let’s say we have a ShopInventory which maintains a list of products. Later on, we took over another store inventory which sells groceries. We now want to add those items to our ShopInventory. The problem we have here is that although the GroceryItem is just a type of product but is unrelated to the Product interface.
To solve this problem, we’ll use the adapter pattern. We’ll create a GroceryItemAdapter which will implement the Product interface:
With the help of an adapter, we’ll now be able to treat the GroceryItem as a Product without changing anything in the third-party code(GroceryItem).
Let’s first start by defining a Product and a ShopInventory class:
public interface Product { String getName(); double getPrice(); } public class ShopInventory { private List<Product> products; public ShopInventory() { this.products = new ArrayList<>(); } public void addProduct(Product product) { this.products.add(product); } public void removeProduct(Product product) { this.products.remove(product); } }
The third-party store that we have just taken over holds GroceryItem‘s:
//third-party code public class GroceryItem { String itemName; int costPerUnit; //constructor, getters and setters }
Since our ShopInventory only holds items of type Product, let’s create an adapter for the newly introduced GroceryItem:
public class GroceryItemAdapter implements Product { private GroceryItem groceryItem; public GroceryItemAdapter(GroceryItem groceryItem) { this.groceryItem = groceryItem; } public String getName() { return groceryItem.getItemName(); } public double getPrice() { return groceryItem.getCostPerUnit(); } }
With that, we can now add both our regular products and the grocery items to our ShopInventory:
//code in our main method ShopInventory inventory = new ShopInventory(); //adding regular store products - ones that implement Product interface inventory.addProduct(new CosmeticProduct("Lavie Handbag", 5000.0)); inventory.addProduct(new FitnessProduct("Yoga SmartFit", 2000.75)); //adding GroceryItem to the store using an adapter GroceryItem groceryItem = new GroceryItem("Wheat Flour", 100); inventory.addProduct(new GroceryItemAdapter(groceryItem));
The adapter pattern helps us to connect two incompatible interfaces exposing the same business functionality.
With an adapter pattern, we convert an existing interface to another interface that the client code expects.
hi, This is really very nice tutorial. it is very clearly given good examples to learn nicely. thanks for it.