Adapter Design Pattern

Design Pattern Tutorial Series

Adapter Design Pattern in Java - 5-Step Guide

The Adapter Pattern is a simple, yet convenient, utility, which you will most certainly find good use of.

The pattern uses and interface and its implementation to create a layer around another object, which then allows the behavior of the object to be converted into a desired form

Although it manages the behaviour of another class, is does not change it in any way. It should therefore not come as a shock that the adapter pattern is categorized as a structual design pattern.

It is one of the many design patterns, which utilize interfaces, to enable decoupled code structure. Similar to the for example the strategy pattern.

Table of Contents

adapter-design-patterns-in-java-overview-INTEGU

Step 1 - The Objective

The objective for this tutorial will be to create a universal hotel booking platform. This service should be able to show available rooms and book a room.

The problem occurs when we discover that our list of hotels all require their own unique communication pattern. As an example, some hotels can print out the list of available rooms themselves. Meanwhile others only provide us with a list of rooms and require us to print them out (e.g. BaliHotel).

This is of cause an inconvenience for us, since we cannot rely on the hotels to follow the same rules. However, this is where the adapter pattern can help us.

Before showing how the adapter pattern will be able to help us solve the objective, let’s see how it could be solved without.

adapter-design-pattern-objective-INTEGU

Step 2 - Working With Concrete Hotels

If we were to solve the basic objective without the adapter pattern, we could potentially be forced to code the interaction for each of the hotels within the same context.

This means we would have to identify how each of the hotel’s functionalities work for each time we were to use it. Dependent on how the hotel classes have been setup, this will likely cause a lot of frustration for any developer.

 

Additionally, since the hotels do not share a common functionality pattern, it is neither possible to swap between the hotels. This structure is therefore most certainly not decoupled.

adapter-design-pattern-disadvantage-INTEGU
import java.util.List;
public class Main {
    public static void main(String[] args) {
        BaliHotel baliHotel = new BaliHotel();
        List allAvailableRooms = baliHotel.getAllAvailableRooms();
        System.out.println("Rooms Available:");
        allAvailableRooms.forEach(room -> System.out.println(room.getRoomNumber()));
        baliHotel.bookRoom(104);
        HongKongHotel hongKongHotel = new HongKongHotel();
        hongKongHotel.printAvailableRooms();
        boolean withBreakfast = true;
        hongKongHotel.bookRoom(11, withBreakfast);
    }
}

Step 3 - Concept Of The Adapter Pattern

Now that we have highlighted the downsides of solving the objective without the adapter pattern, let’s see how the design pattern works and how it can help us.

The adapter pattern can be separated into three classes: The Target, the Adapter, and the Adaptee.

The target is the intended common functionality which we want all hotel classes to follow. This is therefore represented by an interface, which states the two main methods of all hotels: printAvailableRooms() and bookByRoomNumber.

The adapter is the implementation of the target interface. For each variation of hotel there needs to be a unique adapter, which specifies how to convert the functionality of the hotel into the desired functionality of the target interface.

The conversion logics are thereby hidden away inside its own class. This enables the main context to only work with the target interface. Thereby enabling decoupled code structure, as the interface versions of the individual hotels can be swapped between each other.

The final type of class, the adaptee, refers to the object, which the adapter is converting. In this case, that would be the individual hotel classes.

With the core concept of the adapter design pattern outlined, it has become time to investigate the class diagram.

adapter-design-pattern-concept-of-the-adapter-pattern-INTEGU

Step 4 - Class Diagram (UML)

As we can see from the class diagram, the adapter pattern is nothing more then one interface and its implementation.

As explained in the previous section the interface is a representation of how we expect to interact with all our hotel classes (Target), while the implementation is the specific changes required to convert each of the hotels functionalities into those of the target (Adapter).

Since the implementation of the target interface is specific to a hotel class (Adaptee), it will contain an instance of that specific class.

adapter-design-pattern-class-diagram-INTEGU

Step 5 - Code (Java)

Given that code is sometimes difficult to learn through concepts and theory, I provide the code for the example.

Hopefully, this will be sufficient for you to learn to identify and implement the adapter pattern in your future endeavors as a software developer.

Adaptee

import java.util.ArrayList;
import java.util.List;
public class BaliHotel {
    private List availableRooms = new ArrayList<>();
    public BaliHotel() {
        availableRooms.add(new Room(104));
        availableRooms.add(new Room(210));
        availableRooms.add(new Room(307));
        availableRooms.add(new Room(400));
    }
    public List getAllAvailableRooms() {
        return availableRooms;
    }
    public void bookRoom(int roomNumber) {
        Room bookedRoom = availableRooms.stream()
                .filter(room -> room.getRoomNumber() == roomNumber)
                .findFirst()
                .orElse(null);
        if(bookedRoom != null){
            availableRooms.remove(bookedRoom);
            System.out.println("Room " + roomNumber + " has been booked.");
        }else{
            System.out.println("Requested room was not available.");
        }
    }
}

Adapter

import java.util.List;
public class BaliHotelAdapter implements HotelTarget {
    private final BaliHotel hotel;
    public BaliHotelAdapter(BaliHotel hotel) {
        this.hotel = hotel;
    }
    @Override
    public void printAvailableRooms() {
        List allAvailableRooms = hotel.getAllAvailableRooms();
        System.out.println("Rooms Available:");
        allAvailableRooms.forEach(room -> System.out.println(room.getRoomNumber()));
    }
    @Override
    public void bookByRoomNumber(int roomNumber) {
        hotel.bookRoom(roomNumber);
    }
}

Target

public interface HotelTarget {
    void printAvailableRooms();
    void bookByRoomNumber(int roomNumber);
}

How to use the Adapter Pattern

public class Main {
    public static void main(String[] args) {
        HotelTarget hotel = new BaliHotelAdapter(new BaliHotel());
        hotel.printAvailableRooms();
        hotel.bookByRoomNumber(104);
        hotel = new HonKongHotelAdapter(new HongKongHotel());
        hotel.printAvailableRooms();
        hotel.bookByRoomNumber(11);
    }
}

Recommended Reading

Article

  • Theoretical walkthrough – Source Making – Blog
  • Practical walkthrough – Tutorialspoint – Blog
  • Practical walkthrough – Springframework Guru – Blog

Tools

  • Camtasia – Used for illustrations – Camtasia

Books

Video Tutorial 

  • Theoretical  (based on “Head-First: Design Patterns”) – Christopher Okhravi – YouTube
  • Practical – Derek Banas – YouTube
  •  

About

Hi, I'm the Author

My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT. 

I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities. 

The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.

If you like the idea of that, I would encourage you to sign up for the newsletter.

Cheers! 🍺

Didn't Find What You Were Looking For?

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Scroll to Top